Every engineer knows technical debt and every engineer has a different idea what it actually is. All project's suffer from it and not having a clear understanding what it is makes it hard to explain to managers why technical debt needs to be addressed and what addressing it actually means.
Let's dive into some ideas about what technical debt might be.
Bad code
For most engineers, the initial feeling is that technical debt is about "bad code" or "code smells". This idea may have some resemblance to the actual truth but falls short. For one reason, because "bad code" tends to be a subjective thing.
Sometimes "bad code" is just a disagreement on architecture, code-style or paradigm used (OOP, FP). Sometimes, code is objectively bad but just solves a small and uninteresting side-task which wasn't worth investing a lot of effort, architectural or style-wise. Think a shell script running some routine task. It might not be pretty but it gets the job done, has no architectural implications on other code and is unlikely to ever require a change.
It's also difficult to reason with management about what the effects of "bad code" are. We get that it's not pretty but how much does it cost us? And how do we guarantee that rewriting that ugly piece of sh*t doesn't introduce new "bad code"?
Lack of understanding
Ward Cunningham, who coined the term "technical debt" explains it as a lack of understanding (see this youtube video for a reflection on this idea).
- More often than not, software is (needs to be) written without a full understanding of the problem it is supposed to solve
- As a result, the program inherits a lack of understanding of the problem
- Once that understanding of the problem becomes better over time, the program can be improved
If this process of aligning the program with the problem understanding by reorganizing (refactoring) it doesn't happen, the cost of this debt becomes apparent. Confusion builds, programmers have a harder and harder time understanding the program because it doesn't align with the problem anymore.
This interpretation also contradicts the idea of technical debt being "bad code". Because writing a program without fully understanding the problem doesn't imply that the code is bad. Quite the opposite: it requires the code to be clean because it is, at the time of writing, already clear that it has to be refactored in the future. And clean code is easier to refactor than bad code.
As a side-note, it also becomes clear, that technical debt has a close connection to agile programming. Working in uncertainty, without a full problem understanding, refactoring later, leads to the iterative process agile was conceived for.
Mechanics of technical debt
It's funny how Cunningham coined the term "technical debt" while (or because) he was working in a financial software project at that time. Because technical debt shares so many effects of financial debt.
Technical debt is time borrowed from the future. It's the part of the program you didn't complete because you didn't know all requirements. It's the unit test you didn't write because you had no time. It's the styles you didn't polish because the feature had to go live. It's the code-duplication you didn't replace with a generalized solution because there was no time for it. It's that "don't worry about it, we'll fix it later" which never happens.
Whenever you (have to) cut corners like this, you didn't spend time in the present and didn't complete all of the work. But unfinished work has to be finished eventually, causing you to spend time somewhere in the future. Hence technical debt being borrowed time.
Technical debt has the same implications financial debt has. Specifically ...
... technical debt comes with interest payments. That unit test you didn't write? Sorry, it couldn't help catching that bug forcing you to divert your work for hours. That code-duplication and missing general solution? Turns out, it doesn't exist because you never made it and you're duplicating code again. That "don't worry, we'll fix it later"? Guess what, you had all reason to worry.
Whenever your wasting time, stumbling over these issues, you're paying interest to the future you borrowed from.
... technical debt comes with overindebtedness. The more you borrow, the higher your interest payment becomes. Eventually you reach the point where the interest exceeds the available time. Most programmers have lived through a software project which slowly but surely was grinding to a halt. Because technical debt was added and added and never repayed. It became a software project which was overindebted, causing interest eating away available time, causing progress to get close to zero.
As a side-note: this is also why rewrites over overindebted code bases fail so often with a lot of technical debt already included again before they even finish. Because programmers being programmers either think that technical debt is a technical problem. Or maybe realize that it's an organizational problem but still believe they can code their way out of it.
Explaining technical debt
I think the key to making technical debt understandable is to highlight a simple fact: technical debt is unfinished work which is to be finished in the future and therefore is simply borrowed time.
Once this is understood, it is easy to relate the idea of interest payments and overindebtedness to progress and velocity. If you create a backlog of technical debt issues, you may be able to corelate it's size with team velocity to proove this point with actual numbers. But the idea should come natural, even without putting a precise number on the interest rate your backlog/velocity ratio implies.
Cost of technical debt
After the explanations above, some cost of technical debt should be clear by now:
- Slowdown in progress, to zero in extreme cases
- Increasing instability of the program
- Increasing disconnect between the function of the program and the actual problem it aims to solve
Another important, late, cost is turnover: working in a overindebted environment is extremely consuming and frustrating. People start to leave and the talented people leave first. This further increases the problem because with talented people also most of the (still existing) problem understanding laves.
The end
It's not an issue to introduce technical debt. It's an issue to not repay it. Be a good debitor, pay your interest and some of your debt, every week.