I’ve always been a big fan of the “technical debt” analogy. The parallels to real debt are amusingly spot-on. For example, technical debt, like financial debt, incurs interest. If an organization accumulates too much technical debt, the organization ends up in a situation where productivity is impossible—technical bankruptcy.
I’ve recently noticed some ways in which the technical debt analogy isn’t perfect, though. I also have another analogy that I think is more fitting in certain ways.
You can’t just “not use the credit card”
In real life it’s possible not to go into debt. Just don’t use a credit card, get a mortgage, buy a car on a loan, etc.
In software it’s not possible to live “technical-debt-free”. Technical debt accumulates automatically. I’ll explain what I mean.
I recently worked on an application where a certain resource had queuing ability. You could mark items as queued, view a list of queued vs. not queued items, and download a CSV of what was queued. I like to think that the code I wrote for this feature was clean and DRY and reasonably free of technical debt.
Some weeks later I was asked to add a new resource to the application which had roughly similar (but not identical) queuing capabilities. I was able to reuse some of my original queuing code to keep things as DRY as possible, but most of the queuing code was so deeply baked into the original feature that it couldn’t be extracted and made generic without some serious thought and work. The only viable way to build the new queuing-related feature was to 1) consciously introduce duplication and then 2) refactor.
It’s arguable that I didn’t absolutely have to consciously introduce duplication, that I could have removed duplication as I went. I don’t typically find this sort of approach very possible though. It’s usually only after I write a bad implementation of something that I’m able to step back and see how it can be made good.
I’ll provide another quick example. Let’s say I’m working on an application that has four different CRUD interfaces. The CRUD interfaces are pretty similar, but not so similar that they could be considered duplicative of each other. I wouldn’t really consider myself to have technical debt at that point. But what about when I grow to 30 similar CRUD interfaces? At that point any duplication among the CRUD code becomes acutely painful. At that point I certainly have technical debt.
Alternate analogy: the sawblade
I still like the technical debt analogy but I’d like to introduce a new one. It’s not my idea. I got the idea from Stephen Covey’s 7 Habits of Highly Effective People.
There’s a story in the book of a man frantically sawing at a tree. He has been sawing for hours. Another man approaches him and says, “Why don’t you take ten minutes and sharpen the saw?” The first man says, “Are you kidding me?! I’m too busy sawing!”
To me, paying down technical debt is like sharpening the saw. You’re hitting pause on production work and making an investment today so you can work faster tomorrow.
The way in which I think the sawblade analogy is more fitting than technical debt is that a saw gets duller just from normal use, just like a codebase gets worse over time unless the maintainers regularly take a step back and make improvements. The sharper the blade is kept, the faster the team will be able to work.