Some people argue that the main taks of a developer is to deliever working, value-bringing software to the customer and idealistic concepts such as code quality should not hinder that primary task. They acknowledge that it is good to strive for good code quality but say that sometimes code quality must give way to the quick deliverance of outcomes to the customer. After having worked on the code base so rotten that it drove less resistant programmers mad I have to strongly disagree. Code quality is not an abstract concept that has a value only in the developers’ world, it is a very real thing, which translates directly to money, namely if you are missing it, it translates into great financial losses over the time.
I don’t think I am an extremist. I know that code quality can never be perfect, it can always be improved (as Uncle Bob shows e.g. in CC’s Successive Refinement) and thus it is always important to find the proper level of sufficient quality. And I admit that there is code where quality doesn’t matter that much, like one-shot utilities which you use once and throw away. But when speaking about enterprise software, which will live or 5, 10, 20 years, code quality is not anything that can be sacrificed. You may gain temporary speedup by using a quick hack solution but you are thus creating a technical debt, which will be paid for several times most likely already during the development of the software and certainly during its maintenance and further development over its long life-span. Trust me, I’ve been there, I’ve seen it, I’ve paid the price and cursed the authors of the hack.
What is code quality?
To make myself clear I should explain what I mean by the term code quality:
- Proper structuring of the code
- separation, isolation and “condensation” of individual concerns so that one piece of code does one particular thing, which is not done by any other piece of code – thus if you need to change that functionality, you have exactly one place you need to touch
- short, simple methods, relatively small classes (thanks to not mixing different concerns in the same class) – for long, overly complex classes and methods are very hard to understand and modify
- minimalization of dependencies between classes and modules so that it is simpler to change any part of the code
- Readability – expressive method, class and variable names, structuring the code so that it reads as a story – during the lifetime of an enterprise project, many developers will come and go and the code will be read much more often than being written
- Tests – though not part of the code base directly, unit tests are an enabling and enforcing factor for many code quality characteristics
Regarding code quality, I really appreciate Kent Beck’s Four Simple Design Rules.
You will pay a lot for neglecting code quality
If you don’t care for code quality you will end up with spaghetti code, where different concerns (presentation, business logic, security, logging, different business requirements, …) are so much intertwined that nobody can ever separate them again. Long pieces of code doing thousand different things – the same things at many places via copy&paste programming – containing complicated, multi-level if-else statements, preferably using magic constants and mysteriously named variables, blocks of code without any clear purpose that nobody knows what they are good for but nobody dares to remove them… . Changing anything in such code is highly risky because often you need to change it at many places (which you don’t know about). Trying to understand the code will take you lot of time with the likely result that your brain will burn before you manage to grasp what, why, and how the code is doing. You run a high risk of inadverently breaking something and because you have no unit tests – and cannot create any because the code has no units, it is an organic, amorphic beast – there is nothing to notify you about the problem unless it is too late.
Of course this is worse case scenario, where quality has been neglected both in the large scale, i.e. the architectural structure of the code, and the micro-scale of individual objects and methods. Of those two the first one is worse for it makes it impossible to improve the code part by part but both of them tend to lead to further decay of the code. Developers working on it will learn the wrong habits and contribute further to the fall.
If the software is being used and further evoled during 5, 10 years, many people will try to work on it, and each of them will struggle with those problems and pay for them with time when trying to understand the code, when trying to modify the non-modular, amorphic, copy&paste code absolutely unfit for any evolvability, and finally when hunting bugs caused by those failed attempts. And the time of those people is quite expensive and it is the customer, originaly supposed to profit from the quick hack solutions, who pays the bill.
Code quality, especially on the overall structural level, is an essential property of enterprise software, which translates directly to financial losses or gains as the software is further maintained, modified and adjusted. The customer may not understand this for him invisible property and thus it is our duty as techniciants to explain it and care for it. We must strive for good code quality so that the code will be able to live on without rotting over the time. The quality will never be perfect, but it must be good enough – and this is partly measurable with the various complexity metrics etc. – and we should follow the uncle Bob’s boy scoute rule of code quality: when you are working on a piece of code, return it in a better (and never worse!) state then you got it. That means that you shouldn’t hesistate to do small scale improvements when you see an opportunity for them. The result will be that the overall quality of the code will improve over the time instead of decaying, as is usually the case. The wallet of the customer will love you for that.
Update: I’ve stumbled upon a blog documenting some of the abominations you can meet in a no-quality code: The worst codebase I’ve seen in my life
Update 2: As one of the readers has pointed out, a product with a low-quality code can be very successful, as Gojko Adzic shows on the example of Hudson (I’m very glad I’ll be on his lecture next We – living in Oslo is great :-)). However this can only hold for some time for the constantly growing technical debt will slowly make any change too expensive and will bring the product to its knees. We therefore must convey to the customer the cost of neglecting quality.
PS: I’d like like to thank Stig for inspiring me to write this post. Talking about traumatic stuff really helps to get over it 😉