Even if you’re an early career software engineer, you’ve most probably heard about the term “technical debt”, especially if you work on codebases that now have a couple of years of work behind, or not necessarily. Peers are using it in various contexts, but pretty often to blame difficulties in what concerns performance issues or delivery time of specific features on projects that have a large codebase, even to sell subjective preferences in terms of structural changes or what technology to choose for a specific purpose as it sounds scary and can be used to persuade not-so-technical people.

But now, taking it concretely, what’s the real deal with technical debt? Is it that scary and when’s the right time to start worrying? If you start a project from scratch, when will technical debt occur? Is there a way to avoid it entirely and what would be the cost of that?

For everyone reading this to have the same reference for a definition, I’m going to continue with some brief explanatory points about what we refer to and what falls under this category when talking about technical debt.

What does technical debt consist of?

The very first thing that could be said when talking about a definition of technical debt is that it describes the result of the actions taken by development teams when favoring delivery speed over well-written code and future-proof design considerations. That means it comes up with consequences and later there will be a need for investing time in fixing it. That’s why it is referred to as a general word that covers everything from bugs to legacy code.

I remember that at the beginning of my career, my first thought when hearing someone talking about technical debt was to assume that there is an entirely unintelligible mess behind it and someone to blame for it. The well-known Uncle Bob points out something valuable related to this, saying that “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 in the future. A mess is always a loss.”

What items fall under the category of technical debt?

What we should get out of here is that technical debt may always be intentional and strategic. Some other folks will classify the “poor job” things as still being technical debt, but unintentional.

Technical debt as a term is considered a metaphor and as metaphors are abstract concepts, a true definition of it is up to interpretation. For this reason, you hear it being used in so many contexts and under different perspectives - because even if we mostly agree upon a set of things that would fall under the category of technical debt, some of us would still have nuanced additional items to add to the list.

So, maybe, a question crossing your mind right now would be: “Ok, so then what kind of items can we add to that list ?”. To answer it, I’ll further dive a bit into some more specific categories proposed by industry representatives.

Speaking of intentional and unintentional technical debt earlier, these two categories were initially proposed by Steve McConnell in his paper called “Managing Technical Debt” in 2007. Later, Martin Fowler took the concept a step further and published the “TechnicalDebtQuadrant” blog post in which he included a quadrant graphic that attempts to categorize technical debt into 4 categories by taking into consideration both the intent and the context. For that, he starts with a pair of “prudent/reckless” debt and then adds “deliberate/inadvertent” to take consciousness into consideration, as it can be visualized:

Tecnical Debt Quadrant

  • deliberate and reckless - the team is aware that a particular decision will result in tech debt but still moves forward because it prioritizes speed over quality; however the team does not invest time in understanding in depth the repercussions of the decision

  • deliberate and prudent - the same context as in the previous item, but the team takes the decision after investing time in analyzing all the consequences

  • inadvertent and reckless - the most harmful type of debt; the team blindly implements a solution due to lack of experience and is unaware of the consequences

  • inadvertent and prudent - the team applies best practices during development but inadvertently generates technical debt due to unseen coding mistakes; usually, debt is identified later and paid quickly; this type of technical debt is related to learning and innovation - if the organization is healthy, individuals will be encouraged and supported in their continuous learning to research and discover improvements that will translate into actions

How to deal with low technical quality

I intentionally ended up the last item’s observation by emphasizing “if the organization is healthy” because I want to further proceed with putting on the table a perspective I had in mind for a while but didn’t get a chance to elaborate in proper words and share. Coincidently, while reading the book “Staff Engineer: Leadership beyond the management track”, I read my thoughts translated and extended so well by Will Larson, that it doesn’t even worth altering his writing. It goes as follows:

“When you accept the premise that low technical quality results from poor decision-making, you start looking for bad judgment, and someone at the company must be the culprit. Is it the previous CTO? Is it the Staff engineer looking at you with a nervous smile? Is it everyone? What if it’s none of those folks, and stranger yet isn’t even your fault either?

In most cases, low technical quality isn’t a crisis. It’s the expected, normal state. Engineers generally make reasonable quality decisions when they make them, and successful companies raise their quality bar over time as they scale, pivot, o shift up-market towards enterprise users. At a well-run and successful company, most of your previous technical decisions won’t meet your current quality threshold. Rather than a failure, closing the gap between your current and target technical quality is a routine, essential part of effective engineering leadership.

[…]

As an engineering leadership team, your goal is to maintain an appropriate technical quality level while devoting as much energy as possible toward the core business. You must balance quality across multiple timeframes, and those timeframes generally have conflicting needs. For example, you’ll do very different work getting that critical partnership out of the door for next week’s deadline versus building a platform that supports launching ten times faster next quarter. Just as your company’s technical quality bar will shift over time, your approach to managing technical quality will evolve in tandem:

  1. fix the hot spots that are causing immediate problems
  2. adopt best practices that are known to improve quality
  3. prioritize leverage points that preserve quality as your software changes
  4. align technical vectors in how your organization changes software
  5. measure technical quality to guide deeper investment
  6. spin up a technical quality team to create systems and tools for quality
  7. run a quality program to measure, track and create accountability

As we dig into this toolkit of approaches, remember to pick the cheapest, most straightforward tool likely to work. Technical quality is a long-term game. There’s no such thing as winning, only learning and earning the chance to keep playing. "

To conclude

The takeaways are most probably clear and they answer the questions addressed in the introduction: No, there’s no such level of deliberation to entirely avoid technical debt as the involved factors are many and this approach is not even agile; It will always be about finding the most efficient compromise for the specific context. What’s important instead, is to invest time in proper analysis, be aware of the long-term consequences of your actions and make sure you’re ready to tackle previous decisions as your software scales.

References