Technical Debt vs. Technical Risk

One of the most useful metaphors in software engineering is Ward Cunningham's technical debt. Definitions and interpretations vary, but technical debt is basically all the stuff you're going to fix later because you were in too much of a hurry to do it right the first time. We all know what it's like to be up against a release deadline, or in the middle of a bug firefight, and we find something that works and we allow it to pass even though we know it's not really right. Some common types of technical debt might include:

  • Using a "private" member of a data structure instead of adding the proper API.

  • Layering violations and circular dependencies.

  • Copying and pasting code instead of creating a more general common function.

  • Adding "garbage" function arguments that change behavior to suit a new use (often to avoid the previous error but really just as bad).

  • Checking the same condition ten different places instead of refactoring to use subclasses, dispatch tables, or any of several other cleaner techniques.

The important thing about the debt metaphor is the idea that it's OK to have some debt as long as it's tracked and kept under control. Sure, it's different when developers add technical debt just because they're lazy twits, but that fits in the metaphor too - akin to people who can't stop abusing their credit cards to buy junk they don't need and can't really afford. The debt metaphor really helps both developers and business types think about the future consequences of their short-term decisions.

But ... is it really debt?

The thing about debt, in the real world, is that it's a known quantity. You know how much debt you have, you know the rate at which it's increasing, and you know what it will take to pay it back. It might be more than you can bear, if you've been careless, but you know. Technical debt usually isn't like that. The problem with all of these shortcuts is not usually a steady and predictable drag on your resources. A project laden with technical debt might get away with that for a very long time, but that becomes less likely as the cruft accumulates. Every ugly shortcut increases the chance that the codebase will run into a sudden and catastrophic failure - a severe and hard-to-fix bug, a missed deadline, or even a simple failure to remain competitive because changing the code safely has become as difficult as crossing a minefield.

That's not debt. That's risk. As in finance, technical risk can be measured and reasoned about, leading to sensible tradeoffs even though there's uncertainty involved. As in finance, avoiding risk altogether is impossible and trying too hard will mean missed opportunities. Some people will manage risk well, and reap rewards from doing so. Others will manage risk poorly, and will fail - not slowly or quietly as with debt, but often quite suddenly and spectacularly.

I'm not saying that the risk metaphor should displace the debt metaphor. They both have their value. However, in my experience, what gets called technical debt is really technical risk more often than not. The important lesson here is to keep them separate. The next time you hear someone talk about technical debt, or are tempted to make a point that way yourself, it might be helpful to think about whether the conversation should really be about technical risk. In particular, the next time somebody says that refactoring some overburdened but critical piece of code is too risky, it might be worth pointing out that failure to refactor carries its own risk. Some people will always pick debt over risk. Framing the discussion as risk vs. risk might be more effective than letting it seem like risk vs. debt.

Comments for this blog entry