I caught up with this thread on Joel’s discussion board today. We software developers will take any opportunity to rant about the bass-ackwards code we have to deal with on a regular basis. For passionate developers, it’s understandable that most code wouldn’t live up to our standards—only a select few projects have the amount of resources necessary to truly pursue perfection. Over time the exposure to imperfect code can condition us with unfair knee-jerk reaction to new code.
How bad is the code really?
The world is full of terrible code. Usually that becomes painfully obvious at maintenance time. When an existing project is opened up for the first time by a new team member, I think the instinct is to see the flaws before the brilliance. What kinds of things make code stinky? Well it depends who you ask, but some possible reasons are:
- Unnecessary duplication of code (under-abstracted)
- Overly complicated code (over-abstracted or unnecessarily clever)
- Too many files/classes
- Giant monolithic classes
- Wrong design patterns applied
- Stupid algorithms
- Failure to use appropriate libraries or framework features (reinventing the wheel)
- Inconsistency (lack of conventions)
- Numerous obvious comments
- No documentation
Anyone whose done their share of code maintenance has probably been annoyed by most of the things on this list one time or another. “If only they had done it this way.” It’s easy to just assume the code sucks based on a first impression. Once you jump to that conclusion, every minor flaw affirms your prejudice.
Let’s step back a minute and give ourselves an ego check. To an experienced developer there are hundreds of nuances that will stick out like a sore thumb, but they are likely to annoy you far more than they actually impact your productivity were you to consider them objectively.
If you’re not careful, your concern for the code boils over into judgement of the previous programmers. Maybe the last guy wasn’t up to snuff in this language, maybe his pet peeves were different, maybe he was just a blathering idiot. Whatever the case, why dwell on it?
I’ve managed to make it through a lot of bad code without slowing down much. Every once and a while a refactoring or straight-up delete and rewrite was necessary, but most of the time I was able to grit my teeth and get some changes done relatively quickly.
Real reasons code “sucks”
The problem facing you is likely to be different from what the last programmer faced. It would be foolish to assume that the software was designed with the same requirements that you have in front of you today. Who’s to say the business goals haven’t changed drastically since then?
You and the last developer have different information. Even after you’ve spent a lot of time on the code and understand all the intricacies and business goals, you still may not know the history of the project. Maybe the code has grown and shrunk and morphed into something completely different from when it started. If it’s time to refactor, maybe that’s your job.
It’s also quite possible that refactoring is not worth it. Good developers innately want maintainable and aesthetically pleasing code, but there is a cost. We can’t write perfect software before we understand it, and we can’t refactor without spending time. The developer is usually in a better position than the manager to assess the long-term cost of not refactoring, but he also has a vested interested in exaggerating that cost. To make a fair assessment, the developer must have a direct business interest. Even then there’s a great deal of uncertainty. It’s always a gamble.
Developers are conditioned to be right. Our job requires a fiercely logical thought process and the ability to make absolute assertions. Being wrong means things are broken, sometimes spectacularly so. And because we think so hard about things in this way, our conclusions are usually well-reasoned. But we are still human, and we still have the same defense mechanisms around our belief systems as everybody else. The insidious thing is that our reasoning blinds us to our own subjectivity. Our open-mindedness is a badge of pride, but also a set of subconscious blinders.
The only really objective thing about software is its output.
Software engineering is about making choices. Some choices are pragmatic (C++ for performance), some are philosophical (Ruby vs Python), but most are an intangible mixture of past experience and future expectations. When you see some code for the first time, the chances that it will mesh with your experience and philosophy are pretty slim. Eventually you may come to appreciate it for what it is, but in the meantime every tradeoff that didn’t follow your current line of thought will irk you.
Software is messy
None of this is to say that there aren’t real quality problems in the software industry—of course there are. But I think it’s worth carefully considering our own motivations and biases before judging how bad the problem really is.
We may not like dealing with inadequately-funded balls of mud, but that’s probably where most of the paying work is. Even in relatively clean code bases, reasonable people can disagree on style or architecture points. Regardless of initial code quality, there will always be difficult and inelegant maintenance that needs to be done. My goal is to keep emotion out of it, and just fix problems. Refactoring is great if a business case can be made, otherwise just slog through as fast as possible without complaining.
Easier said than done, I know.