You have to make that release date. You need more time to get the structure of your modules right, but you don’t have it. Hitting the release date is more important than cleaning your code, so you defer the cleanup to make the deadline. You agree to take on technical debt which you’ll have to pay back later. Speeding up now to hit this release date will make you slower hitting the next one. If you’re not careful, over time, development slows down to a crawl and every feature takes weeks instead of days.
To avoid development deadlock, we need to fully understand technical debt. Otherwise, we’ll ruin our software. Some questions to ask about technical debt management are:
- What exactly is technical debt (and what isn’t)?
- Where does technical debt come from?
- When is it ok to create technical debt?
- How does technical debt hurt development?
- Technical debt management: how can I measure technical debt?
- How can I reduce technical debt?
- How can I avoid technical debt?
What exactly is Technical Debt (and what isn’t)?
According to Ward Cunningham, technical debt describes deferred, necessary work:
Technical Debt includes those internal things that you choose not to do now, but which will impede future development if left undone. This includes deferred refactoring.
Technical Debt doesn’t include deferred functionality, except possibly in edge cases where delivered functionality is “good enough” for the customer, but doesn’t satisfy some standard (e.g., a UI element that isn’t fully compliant with some UI standard).
Further describing technical debt, Fowler wrote:
You have a piece of functionality that you need to add to your system. You see two ways to do it, one is quick to do but is messy – you are sure that it will make further changes harder in the future. The other results in a cleaner design, but will take longer to put in place.
And Uncle Bob reminds us that a mess isn’t technical debt:
A mess is not a technical debt. A mess is just a mess. Technical debt decisions are made based on real project constraints. They are risky, but they can be beneficial. The decision to make a mess is never rational, is always based on laziness and unprofessionalism, and has no chance of paying off in the future. A mess is always a loss.
If your code is messy, it’s always bad – if you defer necessary work, it might be a smart business decision. Unfortunately both, creating a mess and taking on technical debt, lead to similar issues over time.
Let’s look at some examples and see what technical debt is, and what it isn’t.
A typical example for incurring technical debt in code is that huge source file every developer fears to touch. Everyone on the team knows that it needs to be broken into more manageable pieces, but it would delay upcoming features by at least two weeks. Touching this module without refactoring it is adding to the technical debt of your product. Every such change will make the eventual refactoring harder and therefore needs to be paid back later – with interest. The interest you’ll have to pay is the added complexity of every change you added. The module grows with every code addition making its refactoring (and even the decision to do so) ever more difficult.
An example for technical debt from the operations side of things is deploying your application in only one availability zone in your datacenter even though you have demanding uptime requirements. Setting up a split environment, which covers multiple availability zones is more work. It might be necessary to defer this additional work to be able to deliver critical features to your clients. In this scenario, technical debt does not materialize in added complexity but in higher risk of downtime. To avoid necessary work right now, you introduce single points of failure which will ultimately lower your uptime.
So, what isn’t technical debt?
Unnecessary complexity, dirty hacks, and unreadable code are not technical debt. There is no good reason for introducing such a mess in the first place. If developers feel that they don’t have the time to write simple, maintainable code they’re clearly lacking experience and professionalism.
“Single brain know-how” is another phenomenon often described as technical debt. But being dependent on a single person to maintain or run a critical part of your application isn’t technical debt – it’s a lethal threat to your business. You could argue that not sharing know-how because that person needs to deliver critical features is technical debt, but I disagree. No single line of code should go live without a second pair of eyes scrutinizing it. Things like pair programming or code reviews are good, professional practice and should not be traded for the illusion of higher delivery speed.
By reading this far, you should now have a clear idea what is technical debt – and what isn’t. We’ll cover the other questions in upcoming articles. Make sure you subscribe to our blog updates below.