You should definitely write ugly code. People pay me and people like me good money to come in and clean up your mess when adding features becomes an endless exercise in breaking things in unexpected ways for the whole team and productivity plummets.
Actually, I find that it's usually when the ugly code starts to cost them more. Basically, it's a car without brakes. It will get you where you are going, but it would have cost less all together if you'd installed working breaks from the beginning.
To use your analogy, is it better to have a car with no brakes now, or to save up for another year to buy a car with brakes? The problem with the analogy is that it's _obvious_ that you should save up another year because of the danger.
But in startup-world, it's not obvious at all. To really abuse your analogy, if you're being chased by wild hungry bears, you don't care whether the car has brakes.
Brakes generally aren't expensive (obviously, this is all relative... but lets ignore that), so instead of waiting a year, your more likely waiting a few days at most.
The cost of good quality code isn't expensive either, in the short term or even in the long term. However, for the un-or-misinformed, writing good code might seem higher. Indeed, I'll even go so far as to say that for less skilled individuals, good quality code might seem to increase the cost dramatically.
> if you're being chased by wild hungry bears, you don't care whether the car has brakes.
A little planning would mean I wouldn't be in that situation: bears and no brakes. Though, it's amusing coming up with ways I could find myself in that position. =)
The thing with good code is that it's cheaper than bad code.
For instance: it takes me 8 minutes to run the full test suite of an app and make reasonably certain nothing is wrong. It takes me 2 hours to get the same assurance manually. And I'll miss most of the problems.
Another example: I recently implemented a feature where the feature took ~5 days and fixing the whole codebase to make the feature implementable took 20 days. Had the codebase been using certain libraries correctly without ghetto-coding its own solution, the feature would take me ~5 days.
I don't really like the casual acceptance of the total dichotomy between dirty and clean code here. I'll freely admit you don't always get to clean every bit of code and make it pristine, but on the other hand, with only a small amount of effort and perhaps 5ish years experience it becomes pretty easy to pump out clean-ish code at the same rate you can make an utter, total mess, and recover the value of your slightly higher effort in as little as a week or two, a time frame all but the craziest start ups should still be caring about.
Being in a hurry may be license to be "a bit sloppy", but I think it's a mistake to give yourself license to make a total mess, and use your speed as an excuse. For instance, once you're skilled at programming, and assuming you're using a decent language (another thing your startup should be doing), it's at most only slightly slower to refactor something into a function that copy and paste, and that probably still wins on every level the fourth time you reuse a function like that. Well-done unit testing can also have a payback time frame of under a week, in my opinion. You get bigger wins from listening to it guide you through the initial design that you will get from adding it later.
Usually it's when they get their first non-seed round of investment and realise their product doesn't let them grow as fast as they'd like.
Products growing through sales can go without proper cleanup for decades. Friends have told me stories of single SQL queries taking upwards of 15 minutes to run (and then being rewritten in SQL+PHP that does the same in 20 seconds)
> the code they wrote for the sake of beauty is crap.
From my understanding, this is the crux of the article. The problem with this is the misunderstanding of why people employ patterns in programming. It's not for the sake of beauty, but because of sound architectural principles.
Maybe that's how he interprets beauty, but then using the word beauty diminishes why the code was written the way it was written. That beauty is subjective.
The reality is good code and good practices have real measurable value that mere "beauty" does not.
In my experience, "good" code and "pretty" code are the same thing - and similarly for "bad" and "ugly".
Of course, when I say "pretty", I mean well laid-out, properly documented, non-spaghetti code. I've spent far too much of my time tearing out thousands of lines of "bad" code that wasn't written in a way to allow for easy changes.
My issue is the phrase "sake of beauty." This ignores why this code was written. I'm fine with beautiful code. My issue is the use of the word beautiful in such a way as to imply that beauty was the intent. People don't try to write beautiful code, people try to write good code. That it happens to be "beautiful" is a bonus.
Hopefully my point is clear. I guess it's subtle, but I think a crucial difference.
Well there definitely is a real problem he is speaking to, in which people apply patterns out of reverence rather than understanding. They want to be able to say at their next interview or meetup that they've used all these patterns. Anyone who has worked in Big Corp has seen this first hand: a great shining tower of beautiful code which is 80% bullshit and ceremony.
This all sounds great, but I've worked in places where this has been the philosophy.
Unless you have somebody in charge who understands the importance of code quality (and why a bad codebase can be a ticking time bomb) you will find it very difficult to budget time/money for the removal of technical debt.
You will often meet the attitude of "well it works now, why waste time rewriting it?" or "sure, do that. But let's clear this milestone first", "oh, priorities have changed we need to add this new feature first".
This usually gets externalized to developers who end up working excess hours firefighting a horrific codebase or implementing a bunch of features twice, once in the clean codebase and once in the dirty one.
I've had times where I worked 8 hours at work and then came home and worked another 6 getting the new codebase in sync to a point where it could be replaced.
And when people start loosing money because shit is falling apart due to a tangled, buggy codebase without proper tests guess who's ass is on the line?
Thanks, "Technical debt" is the word here. "Beautiful" might not come close to "valuable" in terms of importance, but "Clean" should come close, because accumulating too much crap makes maintenance & feature addition painful. Uncle Bob's "Clean Code" does a great job at detailing that.
> Would you be willing to buy a piece of furniture twice the normal price because the craftsman uses the most expensive tools available? And what would you think of a poor craftsman who, using poor equipment, manages to create great furniture? Who's the best craftsman of the two?
The author forgot to mention most likely alternative here: a poor craftsman uses poor equipment to create poor furniture that breaks easily.
We shouldn't write maintainable code because the idioms might not seem fashionable at some point in the future? Never mind that code is read way more than it's written and that maintenance costs way more than development. Building up massive technical debt is fine in the short term but eventually you'll have to address it and that's going to cripple development on the product. OOP principles aren't a fad, they're fundamental to structuring code in PHP.
The analogy with the furniture is particularly misleading. Would you pay half as much for a chair that occasionally falls over? That takes a long time to get repaired because each of the legs is tightly coupled to one another? I'd rather pay double for the reliable version.
I've worked with a lot of code bases in the past where the developers have had a resentment towards new methodologies and saw people who tried to use new ideas as just trying to show off. It's a disheartening experience to want to use such fashionable concepts as 'objects' only to be told that the way things are done is procedural programming with SQL queries nested in markup like it's 2000 again. In my experience it's been because they've not wanted to invest in learning new things. That's not a good ethos for a programmer. Let's not promote it.
Maintainability and technical debt are very real metrics. It is just question of short-term versus long-term investment. This article prefers short-term investment (as many other startups do). I just wish buyers would include code maintenance costs when evaluating start-up.
If you are writing code for aesthetic purposes of course you are doing it wrong. If you are writing code and balancing delivering features with maintainability. A balance that constantly changes. Then I would argue you are doing it right. Sometimes that balance is just deliver for the deadline, nothing else matters. Sometimes it is this needs to be extensible and maintainable because it's a cornerstone of our product.
You deliberately call it beautiful code, whereas in reality it is clean code. Clean code is not more expensive to deliver than ugly code. It just requires a better calibre of developer i.e. a developer who can express features in a style which others can understand.
Once you have clean code you can take on features more easily and quickly. You can also change personnel more easily. Most importantly of all you can get better confidence that changes won't introduce side affects.
The problem is there are not many people who can do this.
No-one in their right mind (Fowler, Uncle Bob, included) say code should be beautiful as some kind of vain exercise in style over substance.
Absolutely correct. And what clean code leads to is more maintainable and more easily update-able code. Beauty or ugliness is absolutely not a feature. Its a sideline to what clean code is.
Maintainability is totally the high order bit here. And its totally worth getting it right (or at least approximately). Its the anti-thesis to ugly code.
The article really blurs the line between mere code formatting, which can be completely automated to adhere to some guidelines, coding paradigms and software design/architecture.
I'd argue that, for a product that needs to extendible and maintainable, well thought-out software design is at least as important as working code. It takes a bit more planning up front, specifying the system to be developed in terms of well-understandable and well-documented patterns but this time (and hence money) is not lost. It pays back double during both the initial implementation and maintenance.
A well thought out software design takes a lot of tasks off the people who go to implement it. It clearly specifies which parts are to interact and how they can be expected to behave. Therefore it fosters modularity and independent development of modules, which speeds things up and makes maintenance and extending the product easier. And that is what we really want after all. We want to get code and therefore products out quickly, we want to avoid bugs, we want to make sense of the whole thing after a couple of months have passed in order to implement NewFeatureX™.
There are numerous approaches to this. Object-orientation is just one way to do it and sometimes it's not the best way. After all, all these paradigms and schools of thought are but tools to get the job done and as always, it's a good idea to chose the right tool for the job.
The other thing is actual code "beauty" (however one may define it), which ultimately means readabilty. This is important too but it highly depends on what people are used to. That's why there're often coding standards for a given project or a company. Everybody gets used to them and no one needs to rethink when reviewing the code of other developers. There's no better or worse there. The only thing of importance is that it shouldn't be possible to pinpoint who exactly wrote a certain piece of code by just looking at it. If it looks like you wrote it, you'll understand it that much easier because it takes all the burden of messing with strange-looking syntax away.
The "just-get-it-done" approach to software engineering just doesn't work for projects of a certain size. That's probably why we call it "engineering" in the first place.
I had a really great post for this topic about the utility of ugliness in language design. Ocaml provides imperative features but makes them ugly, subtly encouraging a functional approach in most cases. Clojure quite brilliantly makes OOP and heavy Java interop possible but very ugly (because the language's ultimate goal is platform-agnosticism) while making idiomatic Clojure beautiful. Making something ugly is often more powerful than saying "don't do that". So ugliness has a real value, and that's what I originally came here to talk about.
Then I read the OP, which had to go and ruin that by being wrong.
First of all, OOP is not "beautiful". Quite the opposite, I find Delegates and Factories and Visitors to be fucking atrocious from an aesthetic perspective. All that stuff is there to make business people think their metaphors apply to code and to give them a sense that they, the "big picture guys", have a chance at understanding what's going on. They don't.
I've taught. I've designed games. So I understand the importance of aesthetics in any replication process. Making something easy to learn, understand, replicate, use, et al actually comes down to aesthetics. Now, it's a specific kind of aesthetic sense you need. You spend more time on convergent creativity (trimming, simplifying) than on divergence (adornments, gargoyles, "neat" advanced features). You should, at least when you start, ship a simple product that people can use rather than a complex one that you (having grown up with the complexity as it emerged) find "beautiful". With that I agree. It's better to write straightforward "boring" code that works than to apply every programming trick in the book (self-modifying code! three-level syntax quoting!) If the dumb thing works, use it. Complexity will happen on its own, so don't go looking for more.
Not paying attention to code aesthetics and simplicity, however, is a recipe for disaster. If your code is going to be read by other people and you write ugly, unmaintainable code, then... well, good luck with that.
I don't really mind the substance of what the OP is saying (focus on solving problems rather than writing code) but the presentation is awful.
I feel like functional and non-OOP languages are probably unpopular in the corporate world because when you're using one, there is not really any need to have a business analyst design the application in UML diagrams or Microsoft Visio. Java, on the other hand, is perfect for that, if that's what you're looking for. Java and enterprise software were made for each other.
There are two schools of programming that have diverged: low-productivity and high-productivity development. It's not always about language. I know people in the HP world that use traditionally LP languages like Java or C++ for performance reasons. But the horrid mess of a stereotypical JavaJob is the LP development world where, as you said, those horrible Big Designs are created without irony.
The article mentions design patterns, dependency injection, procedural programming, OOP, and all sorts of techniques that aren't categorically "beautiful" or "ugly", so it's really hard to know what point it's making, other than "don't spend time doing work that has no clear benefit."
I am currently working in a environment, i.e. computational neuroscience lab, where getting results quickly is the most important thing and nobody really cares about the aesthetics of the code, heck not even about the resulting program (the "product") created by that programming. We therefore do indeed often write "ugly" and somewhat unclean code.
I can assure you that I have been angry about (my own and others) working but ugly code more often than not, because at some point you lose control and then you don't even understand what is going on anymore. Try making another 'quick' modification to the source base then. Oh and don't forget the fun to read some other PhD student's (scientific quick hack) code, who isn't even in the lab anymore.
Yes yes, "True artists ship". In general though I would say that you can and should strive both for end-user value and overall systems quality.
I agree to a point - the pattern du-jour has little to do with good code. I also agree - to a point - that prototyping should produce results as fast as possible. It's very hard to create something new and novel without rambling prototypes. You need those to feed your intuition on what aspects are critical and what are not.
As a general guideline, though, this is horrible advice. Although it depends on the definition of "ugly". I would pragmatically define beautiful code as something that is as simple as it can be to implement a useful set of end-user functionality, contains only acyclic dependencies, obeys the key-rule of DNRY (do not repeat yourself), is buildable using a single developer action, is preferably automatically deployed ... and so on and so on.
The key metric to beautiful code in my opinion is that the code and it's host system is in every way as simple as it can be. Sometimes you need a few abstraction layers to simplify the total complexity, often you don't.
It's not just the code. It's how it integrates with the rest of the world that matters. The integration points can be productivity multipliers for the organization.
And, as a developer, you can learn all the time. The better systems you build, the better the next system will be (unless it happens to be the second system where you traditionally must try to implement something horribly baroque). You have to be learning constantly to grow as a developer. You have to consciously strive towards simplicity and elegance, because otherwise you will get stuck. If you accept bad code as "good enough" always, I fear you will not grow up to your full potential.
This article is attacking a very narrow and superfluous definition of beauty, that I would instead call fashionable. The beauty of a piece of code should depend not so much on how well statements are aligned and consistency of formatting, and more on how easy it is to understand; the complexity of the task in contrast with the simplicity of the program.
That said, I still take issue with criticizing his narrow definition of code beauty. We should be allowed to dote on our code and make it pretty. Even if it doesn't provide tangible value to the customer, it lets us take pleasure in our craft.
If you still think that design pattern X is fundamentally better than design pattern Y, Z, Carrot, or Potato, you're missing the point. The point is to have something consistent that works. Design patterns reduce the mental load on the maintainer. The point isn't beauty for the sake of beauty, though it does feel nice to have something that is beautiful.
>When facing an implementation choice, should a developer opt for solution A, which uses ugly code, or for solution B, which is beautiful? That's not the right question: from the end user's perspective, the alternative doesn't make any sense. The user won't look at the code, especially if the product is not good enough to be even tried.
"Let us do our work as well,
Both the unseen and the seen;" - Henry Wadsworth Longfellow, The Builders
You can write ugly code that works or you can write beautiful code that works. You can't write beautiful code that doesn't work.
55 comments
[ 5.2 ms ] story [ 127 ms ] threadRelevant blogpost: http://swizec.com/blog/my-very-own-daily-wtf/swizec/5829
Relevant website: http://thedailywtf.com/
But in startup-world, it's not obvious at all. To really abuse your analogy, if you're being chased by wild hungry bears, you don't care whether the car has brakes.
The cost of good quality code isn't expensive either, in the short term or even in the long term. However, for the un-or-misinformed, writing good code might seem higher. Indeed, I'll even go so far as to say that for less skilled individuals, good quality code might seem to increase the cost dramatically.
> if you're being chased by wild hungry bears, you don't care whether the car has brakes.
A little planning would mean I wouldn't be in that situation: bears and no brakes. Though, it's amusing coming up with ways I could find myself in that position. =)
For instance: it takes me 8 minutes to run the full test suite of an app and make reasonably certain nothing is wrong. It takes me 2 hours to get the same assurance manually. And I'll miss most of the problems.
Another example: I recently implemented a feature where the feature took ~5 days and fixing the whole codebase to make the feature implementable took 20 days. Had the codebase been using certain libraries correctly without ghetto-coding its own solution, the feature would take me ~5 days.
Being in a hurry may be license to be "a bit sloppy", but I think it's a mistake to give yourself license to make a total mess, and use your speed as an excuse. For instance, once you're skilled at programming, and assuming you're using a decent language (another thing your startup should be doing), it's at most only slightly slower to refactor something into a function that copy and paste, and that probably still wins on every level the fourth time you reuse a function like that. Well-done unit testing can also have a payback time frame of under a week, in my opinion. You get bigger wins from listening to it guide you through the initial design that you will get from adding it later.
Products growing through sales can go without proper cleanup for decades. Friends have told me stories of single SQL queries taking upwards of 15 minutes to run (and then being rewritten in SQL+PHP that does the same in 20 seconds)
The OP was mostly referring to design patters and a semi-arbitrary measure of "beauty", not specifically advocating writing unmaintainable code.
From my understanding, this is the crux of the article. The problem with this is the misunderstanding of why people employ patterns in programming. It's not for the sake of beauty, but because of sound architectural principles.
Maybe that's how he interprets beauty, but then using the word beauty diminishes why the code was written the way it was written. That beauty is subjective.
The reality is good code and good practices have real measurable value that mere "beauty" does not.
Hopefully my point is clear. I guess it's subtle, but I think a crucial difference.
Indentation style is meaningless in this context.
Unless you have somebody in charge who understands the importance of code quality (and why a bad codebase can be a ticking time bomb) you will find it very difficult to budget time/money for the removal of technical debt.
You will often meet the attitude of "well it works now, why waste time rewriting it?" or "sure, do that. But let's clear this milestone first", "oh, priorities have changed we need to add this new feature first".
This usually gets externalized to developers who end up working excess hours firefighting a horrific codebase or implementing a bunch of features twice, once in the clean codebase and once in the dirty one.
I've had times where I worked 8 hours at work and then came home and worked another 6 getting the new codebase in sync to a point where it could be replaced.
And when people start loosing money because shit is falling apart due to a tangled, buggy codebase without proper tests guess who's ass is on the line?
"Clean" -> Modular, separates concerns, loosely coupled, not in need of significant refactoring, easy to write unit tests for
The author forgot to mention most likely alternative here: a poor craftsman uses poor equipment to create poor furniture that breaks easily.
The analogy with the furniture is particularly misleading. Would you pay half as much for a chair that occasionally falls over? That takes a long time to get repaired because each of the legs is tightly coupled to one another? I'd rather pay double for the reliable version.
I've worked with a lot of code bases in the past where the developers have had a resentment towards new methodologies and saw people who tried to use new ideas as just trying to show off. It's a disheartening experience to want to use such fashionable concepts as 'objects' only to be told that the way things are done is procedural programming with SQL queries nested in markup like it's 2000 again. In my experience it's been because they've not wanted to invest in learning new things. That's not a good ethos for a programmer. Let's not promote it.
You deliberately call it beautiful code, whereas in reality it is clean code. Clean code is not more expensive to deliver than ugly code. It just requires a better calibre of developer i.e. a developer who can express features in a style which others can understand.
Once you have clean code you can take on features more easily and quickly. You can also change personnel more easily. Most importantly of all you can get better confidence that changes won't introduce side affects.
The problem is there are not many people who can do this.
No-one in their right mind (Fowler, Uncle Bob, included) say code should be beautiful as some kind of vain exercise in style over substance.
Maintainability is totally the high order bit here. And its totally worth getting it right (or at least approximately). Its the anti-thesis to ugly code.
The article really blurs the line between mere code formatting, which can be completely automated to adhere to some guidelines, coding paradigms and software design/architecture.
I'd argue that, for a product that needs to extendible and maintainable, well thought-out software design is at least as important as working code. It takes a bit more planning up front, specifying the system to be developed in terms of well-understandable and well-documented patterns but this time (and hence money) is not lost. It pays back double during both the initial implementation and maintenance.
A well thought out software design takes a lot of tasks off the people who go to implement it. It clearly specifies which parts are to interact and how they can be expected to behave. Therefore it fosters modularity and independent development of modules, which speeds things up and makes maintenance and extending the product easier. And that is what we really want after all. We want to get code and therefore products out quickly, we want to avoid bugs, we want to make sense of the whole thing after a couple of months have passed in order to implement NewFeatureX™.
There are numerous approaches to this. Object-orientation is just one way to do it and sometimes it's not the best way. After all, all these paradigms and schools of thought are but tools to get the job done and as always, it's a good idea to chose the right tool for the job.
The other thing is actual code "beauty" (however one may define it), which ultimately means readabilty. This is important too but it highly depends on what people are used to. That's why there're often coding standards for a given project or a company. Everybody gets used to them and no one needs to rethink when reviewing the code of other developers. There's no better or worse there. The only thing of importance is that it shouldn't be possible to pinpoint who exactly wrote a certain piece of code by just looking at it. If it looks like you wrote it, you'll understand it that much easier because it takes all the burden of messing with strange-looking syntax away.
The "just-get-it-done" approach to software engineering just doesn't work for projects of a certain size. That's probably why we call it "engineering" in the first place.
We want clean and simple code, not anything with convoluted patterns.
Then I read the OP, which had to go and ruin that by being wrong.
First of all, OOP is not "beautiful". Quite the opposite, I find Delegates and Factories and Visitors to be fucking atrocious from an aesthetic perspective. All that stuff is there to make business people think their metaphors apply to code and to give them a sense that they, the "big picture guys", have a chance at understanding what's going on. They don't.
I've taught. I've designed games. So I understand the importance of aesthetics in any replication process. Making something easy to learn, understand, replicate, use, et al actually comes down to aesthetics. Now, it's a specific kind of aesthetic sense you need. You spend more time on convergent creativity (trimming, simplifying) than on divergence (adornments, gargoyles, "neat" advanced features). You should, at least when you start, ship a simple product that people can use rather than a complex one that you (having grown up with the complexity as it emerged) find "beautiful". With that I agree. It's better to write straightforward "boring" code that works than to apply every programming trick in the book (self-modifying code! three-level syntax quoting!) If the dumb thing works, use it. Complexity will happen on its own, so don't go looking for more.
Not paying attention to code aesthetics and simplicity, however, is a recipe for disaster. If your code is going to be read by other people and you write ugly, unmaintainable code, then... well, good luck with that.
I don't really mind the substance of what the OP is saying (focus on solving problems rather than writing code) but the presentation is awful.
Best aphorism of the week.
I believe anyone else on your team will waste a lot of time and effort figuring out the spaghetti code you wrote.
Think. Then code.
edit: reworded slightly
I can assure you that I have been angry about (my own and others) working but ugly code more often than not, because at some point you lose control and then you don't even understand what is going on anymore. Try making another 'quick' modification to the source base then. Oh and don't forget the fun to read some other PhD student's (scientific quick hack) code, who isn't even in the lab anymore.
I agree to a point - the pattern du-jour has little to do with good code. I also agree - to a point - that prototyping should produce results as fast as possible. It's very hard to create something new and novel without rambling prototypes. You need those to feed your intuition on what aspects are critical and what are not.
As a general guideline, though, this is horrible advice. Although it depends on the definition of "ugly". I would pragmatically define beautiful code as something that is as simple as it can be to implement a useful set of end-user functionality, contains only acyclic dependencies, obeys the key-rule of DNRY (do not repeat yourself), is buildable using a single developer action, is preferably automatically deployed ... and so on and so on.
The key metric to beautiful code in my opinion is that the code and it's host system is in every way as simple as it can be. Sometimes you need a few abstraction layers to simplify the total complexity, often you don't.
It's not just the code. It's how it integrates with the rest of the world that matters. The integration points can be productivity multipliers for the organization.
And, as a developer, you can learn all the time. The better systems you build, the better the next system will be (unless it happens to be the second system where you traditionally must try to implement something horribly baroque). You have to be learning constantly to grow as a developer. You have to consciously strive towards simplicity and elegance, because otherwise you will get stuck. If you accept bad code as "good enough" always, I fear you will not grow up to your full potential.
That said, I still take issue with criticizing his narrow definition of code beauty. We should be allowed to dote on our code and make it pretty. Even if it doesn't provide tangible value to the customer, it lets us take pleasure in our craft.
>When facing an implementation choice, should a developer opt for solution A, which uses ugly code, or for solution B, which is beautiful? That's not the right question: from the end user's perspective, the alternative doesn't make any sense. The user won't look at the code, especially if the product is not good enough to be even tried.
"Let us do our work as well, Both the unseen and the seen;" - Henry Wadsworth Longfellow, The Builders
You can write ugly code that works or you can write beautiful code that works. You can't write beautiful code that doesn't work.
- Of course, ugly code is fine for experimening, short-lived code, or code that won't be touched again.
- But beautiful code makes me enjoy my work, which is really important.
- It makes lives of other devs better. Devs want more money for working with ugly code (ie. it costs the company money).
- Ugly code supports the culture that aesthetics is not important.