top | item 7184628

Your code may be elegant, but mine works

164 points| mendicantB | 12 years ago |omniti.com

168 comments

order
[+] freyrs3|12 years ago|reply
Reducing software development practices down to these cute catchphrases is a bit disingenuous. If you're writing throwaway code for a client with loose constraints and a tight deadline you'll write code differently then you would when you expect to maintain a long term relationship with a client who expects a high degree of correctness. I'm tired of these trite articles espousing some cute mantra holds as if it's some universal property of software development.
[+] danellis|12 years ago|reply
The worse thing is that he's saying "you shouldn't spend extra time to do the right thing", and then tries to justify that by giving examples of people doing the wrong thing. Nobody is calling spending weeks writing a caching layer for a 20-row database "elegant" or "best practice". That's a complete straw man.
[+] Draiken|12 years ago|reply
Exactly. Specially with the chosen title.

Almost all similar articles I read, are used as some kind of self justification to writing bad code and leaving it there forever.

If you believe the software will fail (won't ever be changed/grow), do whatever you want with it. If you think it'll succeed, stack too many dirty hacks together and you're gonna pay for it later with tons of interest.

Main problem is, too many times this goes "unnoticed", people just take longer and longer to do the same things, but people stay oblivious to the real causes of that technical debt.

[+] dj-wonk|12 years ago|reply
Meta comment: The article: (a) covers enough relevant topics (b) using rather ambiguous terminology (c) while offering sharp opinions (d) about a world of pain (e) that we all experience (f) but can never be solved in general

This is not a bad formula for crafting a blog post that you want to get picked up via HN. It is also a great way to start a discussion that will never end.

[+] fit2rule|12 years ago|reply
>Reducing software development practices down to these cute catchphrases is a bit disingenuous.

Its a bit like Scientology, but without the crazy.

Oh no, wait .. there's plenty of crazy.

[+] candybar|12 years ago|reply
The main reason that I agree with this is that developers are, as a group, the boy who cried wolf. It's not that technical debt doesn't matter or code quality doesn't matter but so many developers complain about technical debt and code quality when their concern is irrelevant or flat-out wrong that it's difficult to distinguish a legitimate concern from complete BS.

Developers very often use technical debt or doing the right thing or similar arguments as an excuse not to understand an existing codebase and past choices, to convince management or fellow developers to rewrite something that doesn't need to be rewritten, or to buy time to learn and try new technologies/methodologies/patterns that are supposed to be better without understanding tradeoffs or to satiate their desire to overengineer and build a cathedral, when a simple cart would suffice. These efforts acrrue, rather than pay off, actual technical debt. A simple hardcoded one-off is a lot easier to throw away or fix than a half-assed "elegant" design with configuration options and tight coupling everywhere.

All this means developers and managers are correct to be skeptical when another developer talks about technical debt as a reason that they can't do something quickly. It's not that elegance and technical debt and doing the right thing, etc, don't matter.

[+] leobelle|12 years ago|reply
I don't know man. I have been buried under mountains of technical debt before. It's a pretty horrifying experience and makes me paranoid about writing bad code. It's kind of like how starvation makes you see food differently. Technical debt isn't a joke.
[+] sutterbomb|12 years ago|reply
I wouldn't go quite as far with the generalization, but this notion is very important.

Just as developers are often skeptical of a business leader's motivation (is it right for customers or just for his/her ego? etc.), business leaders can be skeptical of technical debt and code quality arguments not because of the concepts themselves but the motivations behind the person doing the arguing.

[+] RyanZAG|12 years ago|reply
I managed to read the article before it went down, it was a pretty good read. Hopefully it comes back up soon.

Anyway it makes a good point that business objectives come before "best practices" which I agree with, but you need to be careful when cutting corners that you don't actually sabotage your business objectives. The real discussion is actually on a risk level: if I cut corner X, I can potentially make revenue Y unless cutting corner X causes a problem and I incur loss Z. Cutting that corner is only good if

  P(no problems | cutting corner X) * Y > P (problems | cutting corner X) * Z
If this equation looks tough, it's because it is tough. This is not an easy decision and you really need to be on top of your game to choose correctly. Alternatively, Y must be much bigger than Z and you have some faith in your shortcut. But for most dev work, a lot of the time you're going to be getting that equation wrong if you just guess it and it's why so many experienced devs will tell you not to cut corners.
[+] fennecfoxen|12 years ago|reply
It's also worth noting that he's talking about things like "if your client needs a Christmas promotion and you deliver on Dec 29". This sounds about right. But if you're in a time-sensitive situation and your code will only be used for a brief period of time, your business needs are probably very different than a code-and-maintain-forever situation (e.g. a SaaS offering).

I am currently developing and maintaining a system which powers an ongoing core business process. If it goes down, employees basically sit around unable to accomplish work. I hope that this system will be robust enough to continue operating for years, maybe decades, and anticipate that during that time four or five business units will either transition their processes to this system, or create new processes that use this system. Clean, quality, well-tested and extensible code clearly matter here in a way that they don't for a one-off Christmas 2013 promotion.

[+] dj-wonk|12 years ago|reply
I like seeing this probabilistically!

That said, I think the operative decision is "should I cut the corner?". If so, you should also factor in the p( ___ | not cut corner ) probabilities.

So, you should cut the corner if the benefits exceed the costs. Written out:

    p(~P|C) * b(~P) - p(P|C) * c(P)
    >
    p(~P|~C) * b(~P) - p(P|~C) * c(P)
Symbols: p = probability; b = benefits ($); c = costs ($); P = problems; ~P = no problems; C = cutting corner; ~C = not cutting corner.

Rearranging to:

    p(~P|C) * b(~P) - p(~P|~C) * b(~P)
    >
    p(P|C) * c(P) - p(P|~C) * c(P)
Then you get a simpler form:

    b(~P) * (p(~P|C) - p(~P|~C))
    >
    c(P) * (p(P|C) - p(P|~C))
An amazing fortune awaits any person who can simply evaluate this inequality in real-world situations.

It is also useful to know when the cost of gathering the information to evaluate the expression is not worth the potential benefit!

[+] codelap|12 years ago|reply
This estimate gets easier with a couple decades of experience. Which is why I'm always surprised by the agism vibe that sometimes resonates on HN.
[+] romaniv|12 years ago|reply
If the project is late, it's not done. Period.

Bullshit. Most deadlines in software engineering are fake. There are some that aren't, but they are exceptions, not a rule. If you're writing all your code as if every deadline is the Judgment Day, you're doing software engineering wrong and not making the right trade-offs.

The unfortunate reality is that there are some engineers who will gladly deliver software 5% faster and 600% worse just because it makes them look good with the management. They justify their behavior by all kinds of BS, but in the end it hurts the industry, their clients and the society at large.

(There is another breed of engineers that will deliver software 600% slower and 200% worse because of overcomplicated design. Yeah, that's also a pathology. But it's not like you have to choose only between these two pathologies.)

[+] jarrett|12 years ago|reply
Exactly. The author cites a Christmas promotion as an example. Yes, those types of projects exist, but in my experience, they're a tiny minority. Almost every deadline I've ever faced was set artificially. The developers estimate how long the project will take, they negotiate with management, and one or more deadlines are established. Often these deadlines are missed (not due to the programmers, BTW), and there's no actual harm to the company or the project.

In my view, the reasons for such artificial deadlines are a) so all involved parties can plan their schedules, and b) because an undefined timeline has a tendency to become an infinite timeline. Rarely do these two needs imply dire consequences for a missed deadline (provided it's not missed by an excessive duration).

[+] viraptor|12 years ago|reply
He presents so many false choices it's not even funny. (also we're adults, either you really want to fucking write it, or don't - stars don't help)

> If the client needs a Christmas promotion, and you deliver the best product in the history of promotions -- on December 29th -- it's worthless.

There's almost always another option - if it's going to be a complete mess that will give everyone additional work in January, then maybe the scope needs to be cut and the remaining features polished.

Even if the code is completed, it can be worthless (or worse):

- if it crashes your whole site for all users, rather than just the promotion part

- if it exposes security issues

- if it not only fails on edge cases on the day, but wakes up your on-call people and spoils their christmas with work

> And taking it a step further, a veteran programmer should know when and, most importantly, how to cut corners, if needed, to meet the deadline. Which brings me to my next point: over-engineering.

It must be great to work at a company that only has fully aware veteran programmers that never make mistakes when cutting corners. It's a shame there's no recruitment link.

> This way, though you may be accruing technical debt, you are also accruing revenue immediately, and you can reconcile the debt over time.

A couple of paragraphs before he talked about limiting scope actually. Yet, we're back to the only balance most people talk about - time and money (expected revenue from change). I've seen something different everywhere. You talk about technical debt, you plan to get rid of it, then another big idea comes and you add more technical debt to get the shiny feature out. Getting rid of technical debt happens years later when people simply cannot live with the issues - they turned from annoyance that takes you 5 minutes to workaround into company-wide issues that block releases for days.

He's also ignoring the fact that the technical debt is cummulative - every time you do something quickly you add a couple more minutes to the every following time you need to work on the same code. Sure - it may allow to get this feature out quicker, but it will also force you to cut corners on the next feature - because you don't have the abstractions you need available.

I'm tempted to assume that the author never really had to deal with the issues someone else left in the code, because they also thought they're veteran programmers and know where to cut corners.

[+] ryanjshaw|12 years ago|reply
Well this is a developer working on Christmas promotions. It's a bit difficult to take him seriously. Let's see how he copes on a smallish 20,000+ person hour project scope with a 5 year+ expected maintenance lifetime and then revisit the discussion.
[+] Draiken|12 years ago|reply
The code is elegant AND it works, so it'll beat the one that just works every time.

This kind of post is always the same, but any decent developer knows when you have to just "get it done" and when you should take time to make it the right way. And of course, that dirty code will be refactored later on.

Always using the "f*ing works" strategy just means you're mediocre at writing code. Either because you led the management team to think anything can magically be built in a "hackathon" or you just don't care about what you build.

[+] otterley|12 years ago|reply
> And of course, that dirty code will be refactored later on.

In my experience, the same product development lifecycles and business priorities that led to the dirty code in the first place will cause it to live forever. Code that works doesn't tend to get refactored unless it needs to be revisited for some other business purpose.

[+] MrZongle2|12 years ago|reply
My code might not be that elegant, but it's maintainable.

I've followed "hey, it works" developers who knocked out functionality quickly. Their by-product was Lovecraftian code.

[+] rnovak|12 years ago|reply
Yeah, the code may work, but making changes to it may make me want to shoot myself.

I work with the same types of devs, and modifying/extending their code could lead one to alcoholism. Seriously. No joke.

I have quite honestly considered changing teams, just to get away from a code base that may "work", but induces nightmares.

[+] frenchy|12 years ago|reply
This is a far better metric. Elegance, while a worthwhile goal, is at its best a vague notion and at its worst, a guise for all sorts of leaky abstractions.
[+] EdwardDiego|12 years ago|reply
Yeah, my team has inherited similar code from one particular Boy Wonder. One example was a service that imported JSON from third parties - it was unit tested, but the architecture was so poorly testable that it had mocked dependencies three levels deep. We also picked up a home-rolled reporting tool that was an instant injection of significant technical debt.
[+] j_baker|12 years ago|reply
Your code may f'ing work, but my code works and is elegant. So what if my code takes a little bit longer to write? From a technical perspective, it's easy to see how this is good. Spending a little bit of time to make your code better will save you hours if not days in the long run.

I also have to question whether this is really good from a business perspective. "First mover advantage" really is overrated. Rather than cutting corners to launch your product a couple of days sooner, perhaps you should be focusing on the long term.

Granted, there are all kinds of caveats we can think of. For example, very early startups don't have the option to focus on the long term and just need to ship something. But even then, putting in a little bit of time up front to polish your code will greatly help your velocity for your next couple of features. You are planning on having more features past the first couple, right?

[+] raganwald|12 years ago|reply
Something important is almost never mentioned in all the literature about programming and software development, and as a result we sometimes misunderstand each other.

You're a software developer. Me too. But we may not have the same goals and requirements. In fact there are several different worlds of software development, and different rules apply to different worlds.

http://www.joelonsoftware.com/articles/FiveWorlds.html

[+] tjr|12 years ago|reply
Similarly, paraphrasing (as I don't have my copy right here with me),

Not all software projects are the same, no more than all construction projects are the same. You can quickly nail a dog house together with only vague planning and minimal craftsmanship. But if you want to build a house for people, you have to plan more, pay more attention to what you're doing, and make sure the result meets the local codes. If you want to build a skyscraper, you have to put even more work into planning, robust engineering, and code-meeting than you do with a house.

http://www.amazon.com/Software-Architecture-Primer-John-Reek...

I've worked on software for iPhones and on software for jumbo jets. The two activities almost aren't even the same thing. Drawing on other life experiences, I might liken it to jazz improvisation vs. classical performance, or to mobile phone snapshots vs. professional portraiture. Overlapping, yet different enough that methods which work for one do not necessarily make sense for the other.

[+] whyme|12 years ago|reply
Great article.

Note that much of the attitude comes from a belief that what is good for the company is ultimately good for the engineer.

However, I'll suggest that's not always the case. Take for example one of the OA's reflections:

"Technical debt should be weighted against the actual ROI, because in many cases it is more cost effective to launch early. This way, though you may be accruing technical debt, you are also accruing revenue immediately, and you can reconcile the debt over time."

Unfortunately, dependant upon your company, that last part may never happen and if I were to frequently experience that at a company, well, you better believe I would rather quit and if I couldn't quit I still would rather put my foot down and pump the tech debt argument for all it's worth, otherwise, in the longer term, working there would be a living hell.

I know I'll get a lot of flak for this take, but all I can say is that while I've quit companies like that, I understand why some people couldn't do the same, and at that point it may require some tough love people management in effort to create a brighter future with a healthy work place.

[+] vinceguidry|12 years ago|reply
> Unfortunately, dependant upon your company, that last part may never happen and if I were to frequently experience that at a company, well, you better believe I would rather quit and if I couldn't quit I still would rather put my foot down and pump the tech debt argument for all it's worth, otherwise, in the longer term, working there would be a living hell.

Wish I could upvote you twice.

My company has so much technical debt in the system that we have five people doing the job of three. Technical debt is almost never paid and the result is invariably a big-ass mess.

You might then ask, "well if the company's profitable then what's the effing problem, then?" The answer is that there's a ginormous difference between where they could be and where they are now.

I'm slowly coming to understand that broken is normal. Paying off technical debt can cause your company to mutate superpowers simply because nobody else does it.

[+] tdumitrescu|12 years ago|reply
"This way, though you may be accruing technical debt, you are also accruing revenue immediately, and you can reconcile the debt over time."

The last part of that statement is troubling, because it happens so rarely. I think a lot of devs want to lean towards more engineering "up-front" because they've been smacked repeatedly with the business reality that the first version of that code is what you're going to be stuck working with, and building on top of, for a long time.

[+] antimagic|12 years ago|reply
Yes. "Reconciling technical debt" does not fit in well with the philosphy of the title. Why refactor when you can just write more code that "fucking works".

Of course, those of us with a bit more experience know that a badly designed module can very easily get enmeshed in a system, with the whole system being designed with the bad module's deficiencies being taken into account. Now you don't just have to refactor the bad module, but all of the code around it too, which turns out to be a difficult ask, so nobody does it, and the bad code becomes locked in.

As always, the higher up the software stack you work, the easier it is to justify bad code, but when you are providing infrastructure code, that will be used by applications, you had better be sure that your interfaces are clean, and your implementation stable. Try pushing some inelegant code to the Linux kernel, and you won't enjoy to the experience...

[+] buckbova|12 years ago|reply
As a database architect I disapprove of this message.

Nearly everything is revisited and changed at some point over the life of the product. If the initial design is a hack or not well thought out, the change will likewise be uglier than the original code.

Even worse, if the original code is not understood by the next developer, it will be thrown out and rewritten.

Take the extra time in the early stages to design, think about fault tolerance, possible future enhancements, extensibility, robustness, reusability, etc. It will pay off.

Yes I over engineer nearly everything I design and yes my deadlines are met. With an elegant design, it is often easier to make late changes on a project. If you follow understood design patterns other people can jump into a project and pick it up right away.

[+] lostcolony|12 years ago|reply
I live by a comment Joe Armstrong made on this (from Erlang and OTP in Action):

"Make it work, then make it beautiful, then if you really, really have to, make it fast."

(The quote continues "90 percent of the time, if you make it beautiful, it will already be fast. So really, just make it beautiful!")

[+] bnegreve|12 years ago|reply
> 90 percent of the time, if you make it beautiful, it will already be fast.

In fact, I disagree with this. The reason is that "elegant" usually means "decoupled" whereas many optimizations actually consists in "recoupling" to take advantage of special cases or to share resources among various decoupled objects.

Designing software to be fast and elegant is actually quite challenging problem. Of course, that makes it even more interesting.

[+] robmclarty|12 years ago|reply
Great quote.

I think we all understand that spaghetti code simply adds time to the next feature we want to introduce, probably creates unseen bugs, and might explode. But it's always a balance and nothing is black and white.

I hear a lot of "you're wrong, do it the right way first!" but you gotta balance "the right way" with its context. Code isn't made for code's sake, it's made to do something (like a business objective, like "be able to order a book through my browser"). Businesses are trying, first and foremost, to make profit, however they need to do that. Beautiful code has nothing to do with that goal, but is sometimes a means to that end.

If the code achieves the business objective it was meant to achieve, it's doing its job (however minimally). Customers don't care what the code looks like (if they look at it). They just care that it does what they need to do (like order a book). Businesses don't care what the code looks like as long as it makes profit.

Secondary to the business objective is how that code fits into the greater context of the system-as-a-whole. Obviously badly written code is going to accrue technical debt, which will likely lead to cumulative delays to new features, cause things to break, etc. The extra effort involved in dealing with that debt is obviously going to cost something, which will have an affect on the primary goal of business: profit. But also delaying a feature, to "do it right the first time", that could be earning revenue, is also going to affect profit. The key is to balance it to maximize profit overall.

When I do anything (code, draw, write, cook, paint, dance, whatever) I start by doing it the simple, easy, fast way; I probably fuck it up; then I iterate and try to improve upon it and refactor. Usually in getting something out there I discover new solutions that I would not have seen had I not actually made something and put it into the world where I could look at it and point to it and talk about it with other people. Being an early mover aside, I think this kind of process helps overall quality anyway. And in the meantime I've got something that's at least doing something.

I think Joe Armstrong knows what he's talking about ;)

[+] mattgreenrocks|12 years ago|reply
This sentiment is why I only work in domains that value high-quality work. My definition of high-quality is something that's done well enough that it doesn't have any obvious issues, based upon the current product vision. It should be designed well enough that we can move onto subsequent requirements afterwards.

My clients/employers don't have a say in the quality of the finished product they receive. (They may be angry about this, but my responsibility is to my profession first, and them second.)

[+] badman_ting|12 years ago|reply
Hmm. It's not that I disagree as such, but more that people who talk like this tend to be terrible cowboy coders. But I agree that developers can be annoyingly fussy about things that actually do not matter at all. No argument there.

Plus elegance is often a bullshit notion and when people say it what they really mean is "what I personally like".

[+] nateabele|12 years ago|reply
I used to work at OmniTI. The real irony of this article is that it was written by a guy who's (in)famous for his indecipherable Perl one-liners.

I think that's about all that needs to be said.

[+] kyberias|12 years ago|reply
> I think that's about all that needs to be said.

Yeah, and that's like a perfect definition for "ad hominem" argument.

[+] programminggeek|12 years ago|reply
This is a great excuse to write terrible code that "works" until it goes out and breaks. Then it doesn't work because you saved a little bit of time by cutting corners.

What is the cost of it breaking? $0? $1,000? $10,000?

What is the cost to fix the broken code?

What is the cost to maintain it?

How much developer time do you waste down the line because they have to fix the "working" code?

I say these things because I've seen this attitude expressed in a large codebase and it sucks a lot to work with and has wasted many hours of developers' lives.

Technical debt is almost never paid back. Just know that going in to whatever you are building.

[+] mrweasel|12 years ago|reply
>How much developer time do you waste down the line because they have to fix the "working" code?

That is absolutely spot on. One of the hardest thing is explaining to management that the code your co-worker wrote in a "flash" three years ago is still eating up developer time today. We have a few ill-conceived or badly written systems that seems to eat up time and constantly interfere with new projects. The problems are pretty much invisible to management, because the developers spend a few hours here and there proppring up the badly written systems. Over time you end up having to spend all your time just putting out fires rather than helping the business moving forward.

[+] gamerdonkey|12 years ago|reply
I'm honestly sorry I gave that a pageview.

It's an article chock full of caveats (Best practices vary wildly across the board, except for the ones any decent programmer obviously knows.), straw-men (Someone spending a week to implement caching on a 20-row table probably wasn't crafting elegant code anyway.), and contrived anecdotal examples (Christmas apps must be out by Christmas. My God, what a breakthrough. Most projects are not nearly this straightforward.).

[+] Ologn|12 years ago|reply
> "You hate testing!" 

I started working as a Unix sysadmin in 1996, and while I have always written programs, and have been doing so more heavily lately, I never wrote a program with someone else before. All of my programming has either been programs completely written by me, or small patches sent to existing open source projects. The purpose of testing aside from the most rudimentary always eluded me.

A few months ago I wrote my first program along with a good, professional programmer. I would code, he would code, I would code. He was good, but I noticed some of his changes would break my code. It occurred to me that testing is something of a communication device. I create functionality, I implement the test, then I tell other commiters to run the test suite before commiting code. If the tests do not complete, they know their code will break functionality I made.

I guess this is obvious, but when I read top reasons to do TDD etc. it is usually not mentioned as a prominent reason to do testing, if it is mentioned at all. I do not find tests beyond the most simple kind helpful in my code, but it starts becoming more useful when you have other people modifying the code.

[+] MAGZine|12 years ago|reply
this would fall under regression testing, and is most certainly covered by any list of top reasons to do TDD.
[+] mattgreenrocks|12 years ago|reply
Cache: http://webcache.googleusercontent.com/search?q=cache:zWk8w06...

Actual article text is a bit more nuanced than the linkbait title. I still hate reading sentiments like these because they appeal to the lazy parts of ourselves that don't need any additional encouragement. It's like people revel in their own laziness and failure to follow-through on some things.

Professionals finish the job, regardless of how they feel.

[+] dpacmittal|12 years ago|reply
I must share an anecdote. A recent project was assigned to me which was outsourced to a consulting company, they ditched the project after 80% completion. I was required to do the rest. I went through the code and it was horrible. They had no concept of DRY principle - little code pieces were copy-pasted everywhere. There was no naming convention, variables were randomly names, in some places they made use of ORM, other places had raw SQL queries used with mysql_query() calls. It was a gigantic mess. If the code would've been organised properly, the rest 20% would've taken me 10 days, now I'm not sure how long it's going to take. Even though the code works and whatever they did is functional, but its light years away from maintainable. "Mine works" isn't always a good solution.