In my series on the 13 categories of technical debt, I’ve previously covered Architecture Debt and Build Debt. This post take a look at code debt, probably the kind of technical debt most IT professionals think about when they hear the term “technical debt.”
What Is Code Debt?
As I did in the previous posts, it’s worth looking at the definition in Alves’ paper:
[…] problems found in the source code which can affect negatively the legibility of the code making it more difficult to be maintained. Usually, […] issues related to bad coding practices.
The paper also lists some indicators of code debt. Things like:
- static analysis issues: static analysis tools can identify code smells and bad practices that will have a detrimental effect on the software and its development
- code metrics: certain code metrics like cyclomatic complexity can indicate a certain amount of technical debt
- duplicated code: identical pieces of code in different places may need to be modified together, but developers may overlook some locations and introduce bugs as a consequence
- slow algorithms: badly implemented algorithms can reduce the performance and user experience of an application
In essence, code debt is technical debt located in the actual production code of the software application, i.e. the code that will be executed for the end user. It is code that is hard to read, difficult to modify, or slow to execute. This causes bugs, a slow development pace, a bad user experience and also a bad developer experience.
Causes Of Code Debt
Code Debt can be put in any of the four sections of the technical debt quadrant. The suboptimal code may have been written intentionally or by accident. It may have grown over time. And developers could be aware of the issue or not at all.
But one of the biggest underlying causes of code debt is schedule pressure. This is when developers feel pressured to deliver faster than they can if the were to take the time for a better solution. We’ll see in other categories of technical debt that schedule pressure is a very large contributor to technical debt (this is also something I cover in my “Technical Debt for Managers” talk).
Many developers unfortunately lack the confidence and maturity to push back on managers or customers demanding a solution quickly. Combine this with some over-confidence on the technical side (“sure, we should be able to implement this in a few days”), and they will cut corners. Often, a pressured team will deliver the requested change, but with a good amount of code debt to go with it.
Solving Code Debt
How to solve code debt, depends on the amount you’re confronted with.
A good starting point is the “boy scouts principle”: this principle states that boy or girl scouts should leave the campsite cleaner than how they encountered it. Developers can do the same with code. While (or after) implementing a feature, they can take some time to improve the existing code that surrounds the code they were editing. By doing this often, the amount of code debt is reduced slowly but steadily.
Of course, this assumes we don’t introduce new code debt faster than we can reduce it. A next step up is continuous refactoring. In this practice, teams reserve some proportion of their time (typically 10-20%) to refactor existing code, i.e. improve it without modifying the functionality. Apart from implementing new features, there is a dedicated amount of time to improve existing code.
Certain automated tools like static code analyzers and AI tools can help identify problematic pieces of code. Some will even suggest improvements. A technique like Verraes’ Wall of Technical Debt can also help identify, visualize and prioritize code debt (and in fact, other categories of technical debt as well).
Developers must take care not to tread lightly when refactoring. A good automated test suite and rollback procedures are crucial to have in place. Without it, managers, confronted with regular regression bugs, may no longer trust the team in reducing the code debt.
The Business Case For Reducing Code Debt
Code debt is a big source of bugs and slow performance, causing a bad user experience. As developers spend a lot of time in the code, it is also causes low morale and in some cases a high developer turnover.
Another consequence of code debt is a slower delivery of new features. Because the code has become complex, developers take longer to finish tasks.
I should not need to explain that a bad user experience, demotivated developers and slow delivery is bad for business. A good user experience and a steady pace of features that end users want is what can give a company a competitive advantage.
Reducing the code debt may reduce the pace of delivery for some time. Which is why startups often don’t bother. They’re still trying to get to the market as soon as possible. As long as they don’t have a selling product, they’re just burning money.
But for more mature organizations, it’s worth slowing down in order to achieve a realistic pace of delivering new features with fewer bugs in the near future.