NOTE

What exactly is tech debt?

#software-engineering (40)#tech-debt (4)#clean-code (4)

Every team I’ve worked with has talked about technical debt. Some teams understood how to manage it. A few were crippled by it. And one company actually failed in large part due to unresolved technical debt.

See also the model vs the harness.

What exactly is technical debt?

Technical debt is a measure of how untidy or out-of-date the development work area for a product is.

— Dave Smith

The debt metaphor is a relevant one. The engineer who originally coined the metaphor explained more about it:

With borrowed money, you can do something sooner than you might otherwise, but then until you pay back that money you’ll be paying interest. I thought borrowing money was a good idea, I thought that rushing software out the door to get some experience with it was a good idea, but that of course, you would eventually go back and as you learned things about that software you would repay that loan by refactoring the program to reflect your experience as you acquired it.

— Ward Cunningham

We’ll get to how tech debt happens. But first we should understand some common misconceptions about the cause and nature of technical debt.

Myth 1: “Tech debt” == bad code

What is “bad code” anyway? Good code is probably clean code, and that can be summed up as code that doesn’t force you to make particular decisions in the future. It leaves options open. Bad code doesn’t leave options open and forces implementation constraints that otherwise wouldn’t exist.

I almost never see “bad code” come from “bad developers.” At least not in a production project. (That’s what code review is for.) Most of the “bad code” I run into comes from good developers working under constraints.

Myth 2: Tech debt is wrong

Tech debt is as “wrong” as financial debt is (i.e. it’s not wrong). No, it’s not ideal — it’d be great if you had enough cash for anything you needed — but it’s a valid tool in your toolbox when building products.

Myth 3: Once you build it, it’s free

I think this misconception stems from the belief that software is like construction. In construction, work happens in sequence: the architect designs, workers build, tenants move in. It’s an easy-to-understand metaphor. But it doesn’t apply to software.

Rather than construction, software is more like gardening:

Software is more like gardening — it is more organic than concrete. You plant many things in a garden according to an initial plan and conditions. Some thrive, others are destined to end up as compost. You may move plantings relative to each other to take advantage of the interplay of light and shadow, wind and rain. Overgrown plants get split or pruned, and colors that clash may get moved to more aesthetically pleasing locations. You pull weeds, and you fertilize plantings that are in need of some extra help. You constantly monitor the health of the garden, and make adjustments (to the soil, the plants, the layout) as needed.

The Pragmatic Programmer

In the (incorrect) construction metaphor, most costs are incurred upfront. Any maintenance cost is either nominal or ignored as incidental one-offs.

In the gardening metaphor, building a feature is a single step (like planting a crop) in a long line of work. The bigger the garden, the more maintenance it needs. That’s work outside of replanting to change the layout (refactoring) or expanding the garden and planting new crops (adding new features — which will also need to be maintained).

90% of the total cost of software is related to maintenance. I’ve known this metric for years, but thinking about it still blows my mind.

How did we get into this mess?

Where does tech debt actually come from, though? And can it be avoided?

Another definition of tech debt might be: The difference between where a project is now and where it would be if we started the project from a clean slate with the knowledge we gained along the way.

Tech debt comes from two sources:

  1. Decisions about tradeoffs. Prefer prudent decisions (where you have a good understanding of the nature of the technical debt) over reckless decisions (without taking into consideration the tech debt).
  2. Knowledge (or lack of it) when making decisions about design and implementation.

Ideally, you’d make decisions with full knowledge and without compromising to meet constraints. In reality, you’ll start projects without the full knowledge of how the whole program should be implemented. You’ll also need to make tradeoffs based on constraints like deadlines from stakeholders or cost limitations.

The short answer to “Can tech debt be avoided?” is: yes, but debt is a tool, not an enemy.

Quantifying technical debt

“How much tech debt is there?” All the tech debt. Can you really quantify a concept this abstract?

A good technical backlog will track some of the tech debt you’ll eventually need to pay back. (I’ve seen more tech debt tickets die in a backlog than actually get resolved.) This can help identify specific debt to pay back, but it’s not an accurate way to quantify the total impact of tech debt on your team.

There is a different metric that is both quantifiable and highly correlated with technical debt: maintenance load.

Maintenance load is how much effort your development team spends to keep the existing features running the same as before.

— Chelsea Troy

Maintenance load is a function of the age of a project and the practices used to build it. You measure it in units of ongoing developer effort.

Maintenance load is not equivalent to technical debt. But it’s a pretty good proxy metric for how much tech debt exists in a system and how much it impacts your team. If you need more engineers just to keep things from falling apart, you probably have a lot of tech debt. If you can build a $1B company with a dozen people, you’ve probably got a good handle on your tech debt.