What technical debt is and why you should care

Recently, I have noticed that lots of people have different views on what technical debt is and what it is not. There seems to be some commonground on what the idea is though: make a quick solution now while deferring the additional work of refactoring the solution into a better one. However, the interesting question is: what is a quick solution and what makes a “good” solution good? I thought I’d share my thoughts on those questions and what technical debt is.

What is technical debt, anyway?

Let’s begin by discussing the general problem of developing software.

The whole reason we’re developing software is to solve a particular problem, which we’ll call the problem space. Our job is to come up with a solution to this problem space; this is our solution space. As we develop our program, our understanding of the problem evolves; we learn new things about the problem which we didn’t know before. And as the problem space evolves, so should our solution space, because the problem is that as soon as the gap between the structure of our solution space and problem space grows large, maintainability issues appear. The goal of our software is not only to solve the problem at hand, but also to be adaptable to change as the problem space evolves. Maintaining the latter property is key to increasing the productivity of a team of software developers.

When the solution space’s structure is not aligned with the problem at hand, horrible issues start to arise. Unreadable, rigid, fragile and increasingly untestable code starts to appear. And then the number of bugs increase because of those reasons; more time is spent on maintaining code than actually producing value for the customer. This, in turn, means that each feature we deliver decrease in value. Therefore, it is essential to refactor our code continuously as our understanding of the problem evolves. We should keep the gap between the solution space’s structure and problem space’s structure small. The solution has to be aligned with the problem.

This is the problem technical debt addresses. Technical debt is primarily a metaphor used to communicate the need for refactoring our code as our understanding of the problem evolves.

Sometimes we need to make a quick solution to something in order to be able to meet a deadline. We borrow some time (= money). It’s supposed to be a benefit in the short-term. However, not repaying the technical debt at some point will continually decrease our productivity over time, and this is explained with the idea of paying interest on technical debt. You can view the gap between the structure of the solution space and problem space as the technical debt.

We should avoid paying interest on the technical debt

As I mentioned before, as the gap increases between the structure of the solution space and the problem space, maintainability issues starts to arise. This is because we’re trying to force solutions onto a design which isn’t aligned with the problem. We work around our design rather than with it.
This typically makes it increasingly hard to change the code and maintain it, while time spent on maintaining the code continues to increase. Not only that, since the code also gets increasingly harder to change, so does it getting rid of this problem. This additional work of refactoring the code is the interest on the technical debt.

As soon as we start paying interest on technical debt, i.e. make quick hacks because our design doesn’t support the solution to our problem, we should consider repaying the technical debt. Because if we let the interest pile up for too long, we’ll put ourselves in a situation with lots of extra costs of maintaining our software while not ever having the time to repay the technical debt. That’s quite the predicament we’ve gotten ourselves into. These are extra costs which could’ve been avoided had we paid attention to our deficient design earlier.

Technical debt is not an excuse for writing horrible code

Writing spaghetti code while calling it a quick solution is equivalent to taking a loan with a high interest rate. Remember, the code shouldn’t only solve the problem we’re facing, but it should also be reasonably easy to change. At least, that should be our endeavor.

Technical debt is a communication tool, and like any other tool, technical debt can be misused. There has to be a reason for doing a quick solution vs. a good solution that maintains the integrity of our design. We have to be sure that it actually pays off, because otherwise, what’s the point, really?

Let’s face it, compromises to our design will happen as time goes by. The key is knowing what to compromise on and when. Know the consequences of design decisions: what impact does the solution have on our software in terms of maintainability?

So, now you might be wondering: “how do I know a solution is aligned with the problem?”
Why, I am glad you asked. I think this is the question the area of software architecture addresses. And it just so happens that my blog is dedicated to this particular area, so why don’t you go ahead and read some of my other posts?