Article

Random thoughts about technical debt

September 1st, 2019

If you put ten developers in a room, you end up with ten views on technical debt - and just as many ways to deal with it. We recently had such a situation, and I was frustrated to find out a clear definition eluded me too. So I though I'd take a look at what has been said about technical debt so far.

The definition(s)

From Hackernoon:

Shortcuts to achieve your goal faster, at the cost of uglier, harder to maintain code.

Not a bad start.

TechnoPedia says:

Technical debt is a concept in programming that reflects the extra development work that arises when code that is easy to implement in the short run is used instead of applying the best overall solution.

It's very rare that I know what the "best overall solution" for any problem beyond the trivial. But choosing a lesser option because it is easier to implement sounds about right.

Then there was this one by Shaun McCormick:

...any code that decreases agility as the project matures.

I really like this definition because it leaves out "cost", instead focusing on ease of change - or agility - instead. Any change that makes the next change more difficult (than it could be).

There seems to be one single agreement though. Technical debt is not "bad code". It's not a compromise on quality like "let's skip the tests".

Uncle Bob:

a mess is not a technical debt

I also like this quote from the same article:

When you buy a house and take on a big mortgage debt, you tighten up all your spending and accounting. You clean up your books and your budgets. You behave with increased discipline.

This should be true of software development too, then. In the places where you know your model is not accurate, you must take care not to overspend and add to your debt. If a large new feature needs to be built in that area, you take into account the cost of debt repayment (refactoring).

Is all technical debt created equal?

In many articles there is an attempt to make separate categories of technical debt. Probably most well known is the split between deliberate/inadvertent by Martin Fowler. The most elaborate attempt I found was ontology of technical debt, where there are 13 distinct types of technical debt. Wow.

Maybe all these different types are valid actionable points to improve quality, but calling everything "technical debt" doesn't really help. When we go back to the person who coined the term technical debt, Ward Cunningham, we can at least find the origins of the "debt" part. The analogy was meant to describe the concept to non-technical stakeholders in the financial sector.

Ward Cunningham

Technical debt is having an imperfect model in software (rushed with the intent of having a fast feedback loop) that is not yet altered to reflect new insights.

It should be noted that the cost of keeping those models without updating them is a function of complexity and change frequency (also see Setting the stage: Code complexity - Matthias Noback). The highest "interest" is paid on frequently changing and complex parts of the application.

Something complex that does not change often might not need improvement. Strategic Design is key here.

Another definition of technical debt I came across says this:

Code that is easy to implement in the short run, as opposed to refactoring to a better solution.

Why not take the easiest option?

But if there is an easier solution, what makes the other solution better? Shouldn't we strive for simplicity? The answer is perspective. The "simplicity" is deceptive, because it is taken out of the context of the whole model.

To quote Russ Ackoff:

An architect will change the design of a house to improve the design of a room, only if it improves the overall design of the house.

Taking our model as a whole, our "simple" solution is technical debt if it makes the model less comprehensible.

A locally added if-statement could solve an immedidate problem, but the "overall design of the house" might deteriorate. Looking at the whole system requires some deliberate design of the solution - you need to find the places where the overall design is degrading because of a change.

Is technical debt purely technical?

Technical debt could be described as "work that does not add new functional value" (no new features). But it is a misconception that that work is only technical. Or conversely, that a purely technical story qualifies as technical debt.

Updating a model to reflect reality better is not a technical story at all. It is a story about improving communication with the future developers who will at some point need to work on that part of the model to add a feature. Chances are that this future developer is you. And this improved communication should save you time.

So what does constitute a purely "technical" story? Something like:

upgrade dependency X to version Y

Sure it needs to be done, but this type of story really has no bearing on the model. But such a story also does not fit the earlier descriptions of technical debt. In my opinion, being behind on upgrades is not "technical debt" in the Ward Cunningham sense.

Maybe we need another analogy

When we drive a car over the road, we expect the tires to wear out. At some point, the tires will no longer be fit for their task. No reasonable person would say "let's not waste time on changing these worn-out tires". That would be dangerous and irresponsible. But this is difficult to transfer this idea to software development. Perhaps because of the idea that software does not change after we write it. It looks like a static artifact that will forever perform its task. Have you ever heard those famous last words "Just don't touch it, it works"?

But we should realise that while in our world the "car" might be stationary - the road under it is moving at an ever faster pace! The outside world does not stand still and so we should always actively maintain our system. We should change those worn-out tires, that is just the cost of doing business in software development.

Again, quoting Russ Ackoff (emphasis mine):

A system is a product of the interactions of the parts. The performance of the system depends on how the parts fit - not how they act independently.

If our systems are the product of interactions of parts, most of which we do not build but only depend upon, we better pay full attention to which of those parts are starting to wear out.

But that is maintenance, not technical debt.

Is there light in the darkness?

When it comes to dealing with both technical debt and maintenance, many things have been written. Most of it boils down to three types of advice:

  • Make it visible (have a separate tech debt board), but no stories in the product backlog combined with a free form "reserved time every sprint" (usually between 10% and 20%).

OR:

  • Do have actual stories in the backlog, because there is "no shadow accounting in scrum". Maybe also have spikes included in sprints to plan and estimate those stories.

OR:

  • Include Quality standards and KPI's in the team's Definition Of Done (in order not to make any new debt), but no explicit technical stories. This work is just included in regular stories.

In many articles, the authors switch from one mode to another because the system breaks down somehow. So there does not seem to be a clear winning strategy when it comes to battling technical debt. I have had similar experiences where the current system in place - whatever it is - never seems adequate to combat technical debt and/or keep up maintenance.

The grass is always greener on the other side it seems.

So without advocating for any approach in particular, the best articles I read on the topic where:

And with that, I bring this article to an end.

May your technical interest rates forever be as low as the real interest rates today.

Ramon de la Fuente

Other resources

Ramon de la Fuente

Pointy haired boss