Technical Debt

The Technical Debt Paradox: Why You May Never Want To Be Debt Free?

Writing the code for well-designed, well-implemented software has been a constant endeavor. And yet, as the complexity of use cases increases and the time to deliver decreases, we sometimes make technically poor development choices. These choices can hamper our efficiencies in the future if we don’t deal with them appropriately.

But is it all bad? Does technical debt pose such a significant threat that we should avoid it at any cost? To put things in the proper perspective, let’s take a step back, understand the debt’s financial view, and then come back to the technical one. After all, the word debt is originally from the financial domain.

The Impact of The Financial Debt

Between 2007-2009, the world faced the biggest recession post-world war II. It was the most prolonged recession, lasting for over 18 months, and GDP, Consumption, and Investments fell to their lowest compared to earlier recessions.

The 2007-2009 recession was significant and different from earlier recessions. Rutherford B. Hayes had put it like this, “It is the debtor that is ruined by the hard times.” But in the case of that recession, the entire world ended up paying the interest. As it is, the evils of debt are etched enough in financial and cultural literature. Incidences like these strengthen the mindset that looks at the debt from an entirely negative perspective.

But Wait, It’s Not All Bad

 - Find & Share on GIPHY

via GIPHY

And yet, we all take on the debt. We often rely on credit to fulfill some of our basic needs, including education or housing. And sometimes we finance our iPhone via credit too 🙂 The entire modern economic system (capitalistic) has credit as the foundation. Yuval Noah Harari, in his highly-acclaimed book Sapiens, says this on economic progress;

Over the last 500 years, the idea of progress convinced people to put more and more trust in the future. This trust created credit; credit brought real economic growth; growth strengthened the trust in the future and opened the way for even more credit.

Making Sense of This Paradox

So is the debt good or bad? Is it the only way to make progress? And what about the fall-outs?

Well, the answer, as often, lies in how you approach the debt. Is it strategic? Have you consciously accumulated it? Do you have a strategy in place to pay off this debt before it threatens you? If your answers to these questions are yes, you are better positioned to benefit from the debt. But if the answer is no, you are in trouble. These principles apply to both the financial as well as technical debt.

Technical Debt, What Exactly It Is?

Technical debt refers to bad code. Are there redundant lines in your code? Is the code not readable, or does it flout the clean coding principles? If yes, modifying and extending the code will take more effort and time in the future. These efforts and time grow as the size and complexity of the application increase. Just like you need to pay off the debt with interest sometimes in the future, you need to pay with time and effort for the debt of poor quality code that you write today. But if it is so, why am I saying that it is not all evil? That it can be helpful for us if approached correctly?

The Conscious Debtor

To understand how you can benefit from the technical debt, we first need to know how we accumulate the debt load. There are three primary ways the technical debt gets accumulated. Sometimes, we make conscious decisions to allow it to creep in. For example, a team might choose inheritance over composition because they are aware that their knowledge of the class behavior is partial. They don’t have enough information to define the interfaces right now. However, they decide to return to the design later when they know more about entity behavior. This decision is a conscious one. You also might want to obtain early feedback by releasing the functionality as soon as possible. That can be another basis for such a decision, as debt speeds development and may improve time to market. And to do that, let some part of the code be of inferior quality in the short term. This approach is similar to how we avail the loans for education or housing. We control the nature and extent of such debt. 

The Unknown Unknowns 

An acquaintance of mine built a nice house on the city’s outskirts. That area had no high-rises then. So this family built their home, and on one side, they had a beautiful glass facade adjacent to the garden. The objective was to view the garden from inside the house. A few years pass, and a high-rise is next to their home, facing the glass facade. The new building ruined their privacy.

Software projects are progressively elaborated. The exact needs and complexities uncover with time. Since we don’t know what we don’t know, there are times that the technical debt- design debt and code debt- creep in. Like the glass wall, we make design decisions based on what we know today. The assumptions on which we based those choices may well change tomorrow. And what we thought was a good enough design may become irrelevant and turn into debt.

What’s Good Enough? 

We build houses for protection from elements and have a solid foundation and robust construction. But our homes do not have nuclear-proof bunkers. That’s reserved for presidential residences. So while we worry about safety, we generally do not take it too far. We worry about our health. But we do not stock up on every medicine possible all the time. We worry about safety and health, but we build houses that are good enough for normal conditions, and we only stock medication that will last us a few days.

It is the same with technical debt. If we try to imagine every possible scenario and protect against that, we will perhaps never be able to finish our design. Mark Cuban often said on Shark Tank, “perfection is the enemy of profit.” Any good software development process will need to live with technical debt in some part of the code. Otherwise, we risk spending time and effort behind a feature that customers might never use or will not change much in the future. Remember, the “debt” only becomes debt if it needs to be paid back. By excessive focus on the debt, we might end up spending considerable efforts and time on features that might occupy a very little customer mindshare. It can also reduce the flexibility moving forward, where we need design choices to be open to change.

Unconscious Debt

And then there is the lack of adequate skills. I have seen many programmers flout clean coding principles often. Sometimes through ignorance of these principles altogether, sometimes because they lack the skills to adhere to them, sometimes because they don’t have the time to make informed decisions and refactoring. Repeated use of poor quality code and circumventing sound principles will increase the challenges as the technical debt increases. Just like uncontrolled purchases will max out your credit card, unconsciously introduced code with inferior quality can spiral out of control. So one should be most careful about this kind of debt.

Becoming Debt Free

First, “free” is figurative. If we summarize the article so far into one sentence, it means you will never, and should not strive to, be debt-free. Let me summarize the learnings quickly before we move forward.

  1. Debt is not unwanted in absolute terms. On the contrary, it may be a necessary evil for making real progress.
  2. Consciously and strategically using debt can help you accelerate the pace of development.
  3. Sometimes, choosing the speed of delivery over avoiding the technical debt can help you uncover actual areas of need from a customer perspective. As a result, your teams can better focus their efforts on those crucial areas.
  4. The debt is inevitable for any real progress. So make the best decisions right now, but keep in mind that you will need to refactor at least some part of your code later.

Despite the inevitability and benefits, you can’t let the debt accumulate beyond a point. If a significant part of your code is of poor quality, your future development will suffer. Hence, just like you pay off the financial debt, you need to reduce your technical debt. When it comes to financial debt, here is how we go;

  1. We identify the debts with the highest interest rates and highest EMIs.
  2. We work out a repayment schedule based on the amount of money we have and expected future cash flow.
  3. We start repaying in a disciplined manner, some predefined amount at a regular interval.
  4. If we suddenly have more cash at hand, we may try to pay a little more.
  5. This disciplined approach reduces the more significant debts first, gradually making the debt go away without threatening the cash reserves we need to survive and prosper.

Paying off technical debt should work similarly.

  1. Include the code refactoring tasks in the product backlog.
  2. Identify the areas of software where the debt is high cost. These are the most valuable features to the customers and are seeing higher evolution than other elements.
  3. Calculate the bandwidth for each release. You will need to balance the development of new features and reduce technical debt.
  4. Include & Implement high-priority code refactoring tasks in the iteration plan.
  5. Keep working in critical refactoring areas every iteration. However, you will need to maintain a three-way balance while doing that. You need to improve the old code, protect sufficiently against the introduction of new debt, and deliver value without breaking the momentum.

Last Thoughts

Through this focused approach to technical debt reduction, you will be able to ensure that your code responds efficiently to changes where necessary. Still, you are not introducing rigidity of design, and you are spending the right amount of effort in the right areas. Moreover, as financial debt has enabled economic progress, technical debt can also help increase efficiency. So instead of avoiding it blindly, embrace it, and utilize it to achieve your objectives.

P.S.

Channeling a bit of Confucius, I would say you might have understood these perspectives on technical debt. Still, if you implement it, you will truly understand how to approach it correctly.

  • Identify three areas in your application that have the technical debt with the highest cost. Remember, the areas with the most significant value to the customers are the most critical.
  • Plan for the time, effort, and money to work on those areas.
  • Create the environment to facilitate conversations about technical debt between business and development teams. Such cross-functional communication can help understand customer priorities & focus the efforts better.
  • As technical debt is inevitable and recurring, these activities are continuously ongoing.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.