Technical debt: when metaphors go wrong
I'd like to find an alternative to the term "technical debt", but I doubt I could convince people to adopt it. Technical debt is so ingrained in the programmer's consciousness that we seem to confuse metaphors with synonyms. Metaphors are to synonyms as transvestites are to my wife (and that's an analogy I'm sure she's going to bring up over the dinner table).
Technical debt bears a resemblance to actual debt, but it's not the same thing. Like actual debt, it's accrued in the same currency (skilled labor over time) that must be used to pay it off. Like actual debt, it's often desirable if you need something now and can't wait for it.
We were discussing in email at work when Abigail put the nail in the coffin of the "technical debt is actual debt" debate. Specifically:
- Sometimes it's OK to default on technical debt (code rewrite, proof of concept, business requirements change, and so on)
- Monetary debt has a schedule on which you must pay it. Technical debt does not.
Got that? When you encounter technical debt in your code, you can decide to repay it or not. Try telling that to your bank. Or if it's in an old, stable part of your code which rarely needs updating or changing, is spending money refactoring that code more valuable than adding a new feature which might earn money?
When you see "technical debt", ask yourself, "do I need to repay this now?" If your answer to that is always "yes", you're a zealot and I'd rather not be programming with you in a professional environment even if I welcome your work in an open source environment. Technical debt is not debt, but we've heard it called "debt" for so long that we act as if it really is debt (I'm guilty of this too). Don't make that mistake.
Update: On reddit, one user points out that an unhedged call option is a better metaphor, though I confess it's not one which is likely to catch on.
When you encounter technical debt in your code, you can decide to repay it or not. Try telling that to your bank.
I think that the example you gave is actually one of the most powerful parallels to debt that gives the term "technical debt" strength.
It's not at all uncommon to decide to push off one debt in favor of paying another. It's entirely possible to not pay your debt (technical or not) when you are supposed to. Even if the bank says "You have to pay on the day", you can ignore that. It just makes things worse. Just like technical debt.
I tend to think of it more as technical baggage. Heavy baggage will weigh you down the further you go along, but sometimes you can't go without baggage. You'll also have to keep carrying it if you can't replace it with something lighter or drop it. Lighter baggage is easier to carry, but lots of it can still slow you down. In that sense, every line of code you write is a form of baggage, the question is more about the weight, how long you have to carry it, and what other baggage will be accumulated by carrying it around. Some baggage can be put down and carried further later on.
It's all symbolism though, so I'm not sure it's even possible to find a construct that has a common base that isn't deeply subjective by nature in regard to "what's the point of this metaphor?"
I disagree. Debt is debt - the problem is that a good number of folks don't understand the nature of monetary debt; the lack of understanding is applied to other forms of debt as well.
Rewriting is bankruptcy.
Normal debt does not have to be paid on a schedule. In fact, you can put off the debt as long as you like if you change your expectations. You can choose not to pay and deal with the courts (you can house-squat for years if you know how to work the system). You can go bankrupt, but you have to get lawful approval (other developers, management). You can skip the country (abandon the project at the expense of the stake-holders), but you must go to a country that does not have extradition (another company that doesn't verify references). You can never return to that country (burnt bridges with company management) unless the you're valuable enough (He's the only one that understands this old code from this other project!) or the next administration pardons you (Management change).
You can discard with paying off debt entirely if you operate with a fractional reserve system (clients and stakeholders are dependent on your relationship and perception of value rather than delivered product). Like the fractional reserve system, it will continue only as long as the stakeholders think it works. When they start to get scared that they'll lose something, they start pulling out, and everything falls apart.
Debt never needs to be paid immediately, but there are always consequences. As implied above, entire economic policies are built on this principle.
In incurring debt, as with everything else, there is no objective bad or good, only action and consequence.
@petdance, you wrote: Even if the bank says "You have to pay on the day", you can ignore that. It just makes things worse. Just like technical debt.
When you say "it just makes things worse", I think you're assuming something you need to prove. If it's in an old, stable piece of code which does it's job well and hasn't needed to be changed in ages, it's very difficult to quantify the business value of rewriting it versus adding new features to your code which might pay your bills.
Or think about "proof of concept" code. You may throw it away after finding out that the concept is bad. Do you really want to pay down the technical debt before you delete the code?
Or think about your "every day" code. What some developers view as "technical debt", other developers argue is a design decision. The distinction between the two is not always clear. (I had a concrete example of this, but I find that when I put concrete examples in "theoretical" posts, people often pick apart the examples and ignore the bigger picture).
"Technical debt" seems like such a terrible thing, but as is the case for any system, there are trade-offs involved and when the tradeoffs are decided by dogma, this is very bad. When they're decided by informed risk/reward decisions, this is very good.
I am not saying that there is no such thing as technical debt or that we shouldn't address needed issues as they arise. I'm just saying that many times we address potential issues, even though they may never be a problem. It's a variation of YAGNI. Merely labeling all of these scenarios as "debt" is misleading and not something we should encourage, particularly in a business environment. All serious businesses have debt all the time (yes, even Apple and Google) because that's how finance works. Acceptance that you'll have debt opens up tradeoffs that you wouldn't otherwise have, regardless of whether that debt is technical or monetary.
It just so happens that Martin Fowler wrote about Opportunistic Refactoring the other day, which covers this the way I would have.
In short: yes, the answer is indeed always yes. But it’s a small yes: “leave the code in better shape than you found it”. That implies not shaving too many yaks. Just neaten any code you touch or code you have to look at in the course of other work when you see an obvious opportunity. Small deposits at a time, not huge downpayments. That also means improvements will accrue in those areas of the code that are most often looked at – which is where they are the most needed and where they provide the biggest benefit.
Fundamental structural improvements won’t happen this way, but if you keep up this practice then you’ll need fewer of them in the first place: large-scale structure grows out of small structures, and constantly grooming local structure helps the code grow into tidy global structures. You have to garden the code constantly – then it’ll be less work overall, and that pays forward in improved ease of development. You will still grow faulty large-scale structures, this isn’t magic. But it won’t happen as quickly, and they’ll be easier to tame.
And let’s not forget improved morale. If I have to constantly wade through a big ball of mud and implementing even simple things becomes like pulling teeth, I’m not even compelled to try to do the job well… I just want to get it over with as little effort as possible. That’s no good for the long-term health of the codebase – setting off a snowball effect.
tl;dr: The metaphor goes wrong just if you have a simplistic idea of "regular debt" and thus impose a simplistic idea on the term "technical debt".
tl:
I'll pick on your assumptions/conclusions a bit just because you picked on Andy's assumptions:
Sometimes it's OK to default on technical debt (code rewrite, proof of concept, business requirements change, and so on)
If we want to keep comparing to borrowing money in the bank (though there are many other kinds of monetary debt), it could be acceptable to stop paying your car loan or mortgage if you are okay with the bank taking those things from you (comparable to a rewrite).
Sometimes it's OK or at least acceptable to default on or otherwise ignore (for a while or forever) monetary debt. An investment structured as a loan. The loan from your parents that was really a gift setup as a loan to not make you feel bad.
There are many kinds of monetary debt; just like there are many kinds of technical debt and currencies.
Monetary debt has a schedule on which you must pay it. Technical debt does not.
Monetary debt doesn't always either.
The schedule can be so flexible that for practical purposes there's no schedule.
The schedule can be so far in the future that for practical purposes it's irrelevant.
Current circumstances ("get food/make payroll/pay mortgage today") might make the future obligation (say a financial instrument with a "cliff like" expiration) completely irrelevant in the short-term. Just like when "we need to make this code run this week or we'll lose the customer" makes paying off technical debt get second priority.
Getting another loan to cover the first might be cheap and easy enough that you – at least for a while - don't need to pay it off.
Also: Metaphors are stupid. At least wasting time analyzing the trees and missing the forest is. ;-)
"Monetary debt doesn't always either."
Another term that is au courant in the financial arena is "kicking the can down the road." See Greek bankruptcy.
While metaphors often break down when stretched too far (as e.g condoms) they are quite useful for normal use.