mheroin

i heroin (blog)

about

The unavoidable hack

I start working on a new project. I spend the first couple of days thinking about how everything’s going to work. I draw an architecture of sorts [1] and I get to coding the most problematic stories. During the initial of weeks I feel like I’m progressing a lot and I’m quite happy with how everything’s turning out. I skip some tests because the methods I’m writing are so self contained and trivial that everything feels obvious. There are no edge cases in my code and to an outsider, this piece of fine work I wrote resembles art. Everything is where you’d expect it to be and you can start hacking right away on any class without spending too much wondering what’s going on.

At the end of the first month I start noticing that some of the code I’m writing can be refactored into something more elegant. Most of the times I’ll just stop developing new features and I’ll change the code that’s not up to my standards. It usually doesn’t feel perfect but I think it’s above good. Any serious programmer could read this and think “Hey, this is pretty nice”, and so I keep working, writing new features and refactoring on my free time.

By the end of the second month I notice that things have gotten a lot more complicated. Features that at first would’ve taken 20 minutes are now taking me an hour to write. In the process of growing the software I feel that something’s broken, I fucked it somewhere and now I’m paying for it every time I have to write new code. Edge cases are creeping into every feature and the nice 2-line methods I initially had are now 8 or 10 lines, testing for weird input and breaking Demeter in every imaginable way.

Don’t get me wrong, the code’s still production-ready and I don’t feel too bad about it. It’s code that I can show to any other programmer and not be ashamed, but I’m convinced that at some point either my system out-grew its “architecture” or my motivations are just not as sharp as they were in the beginning.

An interesting point to note here is that this breaking point, what I call “The Unavoidable Hack”, is getting delayed more and more every time I write new software. I’ve worked profesionally as a developer for the last 7 years and if I take a look at what I wrote at the beginning, the unavoidable hack would come up during the first day of coding.

Still, every single project I’ve worked on in the past has gone through this threshold, a point of no return where I just say “Fuck it, it can’t be perfect if I ever want to finish it”. I initially thought that this was related to time constraints, but after having worked on a lot of personal open source projects, I’ve realized that I eventually hit the same problem even if I don’t have any kind of timeline imposed on myself.

I’ve also noticed that none of the big projects that I admire are resilient to this problem. The Rails codebase, inspected daily by hundreds or thousands of developers, still has some really dark corners that after many years still don’t make sense to me. The code for Railscasts, written by someone I deeply admire, has some code that could’ve been written in a clearer way a long time ago. It looks like not even my programming heroes can overcome this problem.

After thinking about this I started wondering: is it possible to write excellent code for a non-trivial piece of software? I use the word excellent instead of perfect because I don’t think there’s such thing as “the perfect code”.

Maybe the last question is unfair, and instead I should be asking myself: Is it worth it to spend so much time on details that on the long run might not be so important? I’m not talking about writing crappy, unmantenainble code that no one can read. I’m talking about code that serves it purpose even if it can be rewritten in a clearer way.

People comes up with excuses for why they do this:

Some of those reasons are pefectly valid, but I still have a voice somwhere in my head telling me that it didn’t have to be this way.

I’m interested then in finding out if there’s such thing as an excellent code base for non-trivial stuff. I want to know if that voice in the back of my brain even matters. I wonder if this is just the nature of software. I question my assumptions about architectures [1]. I want to believe that if I write more software the event of the unavoidable hack will be deferred to a point so far in the future that it won’t matter. Are the Kent Becks, Russ Coxes and Uncle Bobs of the world writing systems that don’t suffer from these problems? Is this even a problem?

[1] I don't believe in software architects. I don't believe in people spending 3 months writing a specification of how everything should be implemented. When I talk about architecture I'm usually referring to the act of picking the hardest problems of the system and then thinking of how to solve them in the context of this program, leaving a note, a drawing or even tests for future reference.

You can discuss this article at Hacker News.