A Technical Debt Crisis Is Brewing in the Land of Software – And Here’s Why
What technical debt is, why it exists, and how to avoid it
On September 15, 2008, Lehman Brothers went bankrupt. It was the climax of the financial crisis around 2008 with enormous economic consequences. The bankruptcy was caused by different factors coming together. One of them was taking on debt. Lots of it. When the housing market collapsed, the debt turned out to be too much to be repaid and the bank went bankrupt.
Is this something that could happen in software development?
According to recent studies, developers spend 30%-50% of their week on code maintenance: debugging, refactoring, writing documentation, etcetera. That means that globally 85 billion is spent on code maintenance per year. Code maintenance goes hand in hand with technical debt: imperfect technical solutions that were implemented to save time, but bring problems in the future. We might very well be in a technical debt crisis and I believe it is time to talk about it.
In this article, I will give an introduction to the world of technical debt. I will go over the definition of the term, the analogy with regular debt, and discuss different types of technical debt. In upcoming articles, I will discuss how to manage technical debt by monitoring and quantifying it.
Being in debt simply means owing something to someone. This something is typically money (but it can also be some type of good). The lender of that money usually asks for something in return on top of receiving their money back in the future. One such thing is interest: an amount of money paid (yearly) by the borrower to the lender until the loan is repaid.
For example, Alice borrows $100 from Bob, with an interest rate of 5%. They agree that Alice will pay back the loan after 10 years. Alice pays $5 per year on interest for 10 years, so after 10 years Bob has $50 and receives his $100 back, for a total of $150. We call the $100 the principal amount and the yearly $5 the interest that is paid.
Note the ratio between principal and interest. In the first years, interest accounts for only a small percentage of the total. After 10 years, one-third of the total amount to be repaid is interest!
Technical debt arises when choosing a non-ideal technical implementation over an ideal one. The most common reason to choose this path is to save time in the present because most of the time you are required to implement the ideal solution in the future anyway.
Furthermore, just like with regular debt, interest is to be paid over technical debt. This comes in many forms but comes down to having to spend more time on changes due to imperfect implementations.
For example, a method is duplicated because extracting it properly is considered too time-consuming. When that method later requires a change, you are required to make two changes, as the code is duplicated. This extra second change is an example of interest on technical debt.
Differences between debt and technical debt
Time is money
Debt and technical debt differ in their unit of measure. Debt is typically expressed in money, but technical debt is expressed in time: it could take 4 hours to refactor a certain class.
These units of measures are the convention, but can actually be interchanged. When owing someone $100 dollars while earning $20 per hour on your job, you could say you have 5 hours of debt.
More interestingly, the other way around, technical debt can be expressed in money. If a programmer earns $30 per hour and takes 4 hours to resolve a piece of technical debt, they can be said to have paid off $120 of technical debt: time is money.
Interest payments on technical debt
Would you take on a loan if you did not know whether the interest rate is going to be 2% or 50%? Or if the lender could ask you for interest on the loan whenever they like?
Companies take on regular debt using clear contracts with creditors. A time period is agreed upon after which the principal amount is to be paid back. Secondly, an interest rate is chosen. Every year the debtor pays the interest on a fixed date. This means that both parties know when payments will take place before the debt is taken on and this gives clarity.
With technical debt this is different. When taking on technical debt, there is no clear interest rate established. Interest will often be paid at irregular intervals. Moreover, the amount of two interest payments will be different. This is visualized in the image above.
Types of technical debt
The boundaries of technical debt are subject to interpretation: different researchers use different boundaries. For this article, I will use the four types of technical debt described by Seaman, C., & Guo, Y. in Measuring and Monitoring Technical Debt.
Test automation debt
Test automation debt is the most simple type of technical debt. It is taken on when choosing not to write an automated test for a piece of code. Another phrasing would be: an uncovered piece of code. What is the principal cost of such a technical debt item? The cost of writing the automated test. Skipping it concretely saves time in the present.
The interest on test automation debt is paid in the following forms:
- Defects: lacking automated tests makes it more likely that bugs are introduced.
- Misunderstanding: well-written automated tests provide the reader clarity on the expected behavior of a piece of code. Lacking these tests can result in future changes lacking comments or lacking adherence to code/architecture guidelines, as the programmer making modifications lacks understanding of the code.
Defect debt refers to malfunctioning pieces of code. The principal cost of defect debt is the cost to modify the code to behave correctly. While its definition and principal cost sound simple, bugs can be complex to resolve as we all have experienced without a doubt.
Interest on defect debt again comes in different forms, all sparked by the impulse to save as much time as possible in the present. Defects never come at a convenient time, as they arise unannounced. To make the pain of having to resolve defects as small as possible, programmers are tempted to simply fix the problem in the code and skip writing an automated test for the situation, skip writing documentation about the situation or skip an architectural abstraction that is appropriate.
Documentation debt arises when code is changed or created without creating or updating documentation for it. The principal cost of this debt is the cost of writing or updating said documentation.
Interest is paid when people have to read or change the code that lacks up-to-date documentation. It takes longer to understand the code and allows for misinterpretation of the code. This in its turn paves the way for introducing defects and deviations from the domain model/desired architecture.
Read more about the importance of commenting here.
Finally, there is design debt. Design debt comprises deviations from the desired design. A good design/system architecture enables programmers to easily extend and modify a system. In this sense "easy" implies that it requires little time or at least less time than when a bad architecture was adopted. The principal cost of a design debt item is the time it takes to refactor the code to adhere to the desired design.
When and how is interest paid on design debt? Firstly, similarly to documentation debt, interest is paid when a design is confusing as this increases development time. It can also easily cause defects when relations are obscured or possible scenarios are hidden by the design. It can also demotivate programmers to write proper documentation as they do not truly understand the code they have to write for a new feature.
Relations between types of technical debt
You might have noticed a pattern in the types of interest for each type of technical debt. Debt of one type yields interest in the other types of technical debt.
Moreover, interest can be paid in the same type of debt as the principal: when fixing a bug in a hurry, it is easy to skip a possible flow and introduce a new bug. When adding a new feature to an application that has poor test coverage, it can be tempting to skip writing automated tests for this feature as well (because the application is a 'lost cause' anyway). The same goes for documentation: if an application contains no comments, you might feel less obligated to add documentation for your new code. Finally, a bad system design makes it cumbersome to make a new part have a good design, as the design typically affects all components.
If we put all interest relations between technical debt types in a graph, we obtain the following:
Technical debt comes with interest to be paid, and this interest takes the form of technical debt as well, revealing a dangerous feedback loop that can exponentially increase the amount of technical debt in a system.
If software developers around the world are spending close to half their work week on fixing unsatisfactory code, the IT industry has a serious problem on its hand. This unsatisfactory code is also called technical debt: imperfect implementations, often executed because of time constraints in the past.
Technical debt consists of a principal cost, time to resolve it, and interest, extra time spent on future tasks due to this technical debt item. Although similar to regular debt, technical debt has a varying interest rate, making its future cost unpredictable.
There are four main types of technical debt:
- Test Automation Debt: uncovered code
- Defect Debt: incorrectnesses in the working of code
- Documentation Debt: lack of proper documentation
- Design Debt: deviations from desired design
Interest on technical debt takes one of these four forms as well, revealing its dangerous property to grow exponentially.
Knowing what technical debt is and what forms it can take in your codebase can help you identify it in time and possibly avoid it.
A word of advice
The purpose of this article was to introduce you to the concept of technical debt and to motivate you to consciously think about when you are taking on technical debt. When taking a shortcut in your code consider the consequences for the future: what future tasks are affected by this and how much?
Technical debt and its exponential growth are something to be taken seriously if we want to avoid ending up in our own technical debt crisis.
What is next?
I wrote this article mainly as an introduction to a series of further articles on technical debt management. Where this article is very theoretical, the next will also aim to give handhelds for managing technical debt in practice.
Hopefully, this article was insightful for those of you not yet familiar with technical debt.
If you have insights or questions about technical debt, please leave them in the comments!
Did you find this article valuable?
Support Ruben Scheedler by becoming a sponsor. Any amount is appreciated!