In this world there are two kinds of software developers. Those who focus on product, and those who focus on code. Most focus on code.
Of course this division is not black and white. Many developers also care about getting things done. But based on my experience, many developers consider the code they commit more important than the actual value added to the product. Or to be more precise, some developers might have difficulties to fully comprehend the business value of their code.
For code-oriented developers, the quality code has intrinsic value as such. In their world, writing poor quality, messy or suboptimal code is an heretic practice that should be avoided at all costs. For code-oriented developers, producing suboptimal code goes against their professional ethics. Being forced to ship a feature or a product sooner at the cost of code quality demotivates them.
Having interviewed dozens of developers, I often used to ask the question “Do you consider code quality more important than timely delivery of the product?” - or some variation of this. Almost exclusively the candidates preferred code quality, even though some of them pointed out the importance to balance between the two.
I understand them. No one wants to admit in job interview that they deliver sloppy code. Even though they did it very efficiently. Having written some open-source code, neither would I share my dirtiest hacks and scripts with public before polishing the code so that it comforts my dignity. And so that I wouldn’t get laughed at, or called out for delivering shit.
What is quality code?
The definition seems to be somewhat subjective. For some, quality code means that the code is readable and “looks nice”. The codebase is well-structured and consistent in naming conventions, indentation practices and so on. The code complies with some coding style standard and follows the best practices of the language.
For others, quality is more about “Does it work as intended?” and “Is there a lot of bugs?” Also other factors such as performance, unit test coverage, good security practices and stability could be counted. However, these can be generalized to be part of product quality which I consider superset of code quality.
Why we need to consider code quality?
Even though a product was well functioning, secure, performant and well tested, the corresponding codebase might be a huge pile of shit from developers’ point of view. This has following negative outcome:
- The codebase becomes difficult and slow to maintain.
- In certain type of applications, the codebase might not scale up well for a larger user-base or more intensive computation.
- The codebase becomes painful to maintain, demotivating developers. As a result, it might become difficult to find experienced developers willing to work with the codebase.
- Further development will more likely introduce new, unexpected issues that are difficult to debug.
- The codebase likely depends on 3rd party components that are eventually deprecated and might be difficult to replace.
- Over the time, the codebase will turn into legacy shit that needs to be rewritten.
So what’s the problem then?
The problem is that many developers evaluate their work through metrics that are visible to them: are they producing high quality code that is easy to read, performant and maintainable. However, the business value of the development work is often evaluated by different metrics such as timely delivery, fulfillment of requirements and absence of obvious bugs.
If you have a team full of developers polishing the code, there’s a chance that you have a very beautiful, nice and performant codebase but you never ship your product. Software developers have a magical ability to pour infinite amount of time and effort on hammering out non-essential details and refactoring the codebase, if that’s what they’re allowed to do.
If the developers fail to recognize the business needs, it may lead to awkward outcome. An important new feature could be stuck in review phase for days - or weeks, because the developers are arguing whether some variable should be a float or a double. An easy fix to a critical bug in production might take days, because the developer feels that the proposed one-liner is “quick and dirty” and they want to “fix it properly”.
Generally a manager or product owner is expected to respond these issues by prioritizing the development work. But on the other hand, managers and product owners might not be always capable to evaluate the development effort required for a certain task, and often they depend on the developers to give their estimate. Furthermore, pushing developers to “deliver faster” rarely leads to a good outcome.
Okay, so what kind of developers we need?
We need developers who focus adding value to the product rather than the code. Developers, who get their daily dopamine dose from delivering working products and services. Sometimes their solutions might be a bit dirty under the hood, but as long those serve the purpose, it’s mostly just fine.
Experienced product-oriented developers do not overlook the quality measures. Quite opposite, actually. Their strength is an ability to identify which quality measures are relevant and to which degree. Code quality is an important thing, but only to the degree the effort contributes to the overall product quality over lifetime of the product.
While being able to write quality code is an important skill for developers, I propose it is equally important to understand the lifecycle of the code and the business context the code is being used. The code has instrumental value, which is to enable a certain feature or a non-functional requirement in a product. But the value of certain piece of code does not exceed the business value of the corresponding feature.
Once proven to work, it makes no sense to spend time polishing a migration script that is run once and then forgotten. Lifecycle of that piece of code is remarkably short. Similarly, when writing a core component of a service that is expected to run in production for years and to be developed further, requirements for code quality are different. A well-thought architecture and a careful implementation will pay itself back over the lifetime of the service.
Keep coding, but do it wisely. In software development nothing is as permanent as a temporary solution. But many software products are more or less temporary solutions.