I’ve always understood technical debt to be work you need to do for non-feature reasons, in order to enable feature work. The work might be needed because you compromised, but I’m surprised at the idea that that’s the only such work you can call debt. Code has a shelf life, and the level of effort required to add a feature can change between now and, say, two years from now, just because the platform or popular standards changed out from under you. I don’t think you accrue debt only by actively borrowing. Your existing built codebase, even if it’s clean, charges interest.
I understand that the article uses “bad code” to talk about code which did not have much time invested into its design; it refers to code which is not very thoughtfully written. However, there’s a corresponding implication that there exists some sort of “good code” which does not accrue debt-like costs over time, and my experience is that code does not age very well in general. Only code written in certain languages, styles, and dialects can still be run today, and it is precisely because of effort put into maintaining toolchains. This effort is a cost; GCC and other compilers require us to pay interest in the form of constant maintenance.
Debt doesn’t have to be understood in its financial meaning. It basically means that an inevitable act is postponed. Some debts grow over time others don’t. Some can be transferred to other actors, some cannot. Some turn into trap doors if they are forgotten. To me a technical debt is that but related to a technical realm. No need to narrow it down further.
RIP, David Graeber. May his debts be forgiven.
When does this debt mature? Can we sell it? Oh, we can only pay it off through labour?
I find the metaphor bankrupt.
No credit check! Bad credit OK! Buy here, pay here!
The term technical debt has helped me often, simply because it captures for a layperson that even though code works, it is not necessarily optimal. No other term has in my experience managed to convey this as a serious consideration.
It’s perfectly fine for me that it doesn’t specify how the code is not optimal. That discussion is usually quite complex anyway, and something that should be left to technical experts.
It works so well that engineers try to use it for everything they don’t like. Seems like the natural progression of language, but that doesn’t make it a good use of the term.
This linguistic prescriptivism is peak STEMlordy attitude: “the common usage of the word, let’s use mine instead”. He’s not inquiring the nature of technical debt, he’s just trying to revert to an older, ideal usage of the word that describes something completely different.
Could we say that technical debt is about intent, not technical details? Something is technical debt if it’s intentionally suboptimal and you want it to be optimal later. A bunch of messy code doesn’t have any technical debt if you never need to clean it up, and clean code has technical debt if you’ll need to make it faster later.
AIUI this is what the author noted as their original understanding of technical debt. And as you noted, in this framework, if there are no consequences then there is no technical debt.
Everything in software is some sort of half-assed metaphor. So when I read the title, I tended to agree with the author.
As I read the essay, however, I found myself more and more disagreeing. I was hoping that the author would make a better metaphor, or provide a more rigorous definition. Instead, they just tore it all apart, and replaced it with another metaphor, “maintenance”. So while I agree with the thrust of the article, I don’t feel like we’ve gotten anywhere. Obviously there was something missing in the word maintenance or we would just use that.
Technical debt is when we leave the project in such a state that we know it’s going to take more effort than it should to modify it later. Note that I used the word project and not the word code. When we begin the work, we understand the problem a certain way. As we engage, we begin to understand the problem in a different way. At some point, the project does enough to make the users happy, but there are parts of it that will be painful to change later
is this a working project that just requires maintenance? Is it a mess? Is it technical debt? I think these are financial questions. Leaving work for later is incurring future cost. The reason the word maintenance does not work is that sometimes there is no future cost: for instance nobody is using our product and we will never have to change it. Likewise, sometimes we can maintain the product without having to change anything for the users, such as when we’re upgrading a database version.
The word bottleneck is good, but the word debt is much more apt for communicating to people who don’t understand what we’re doing. So I am left agreeing with the author that we mix a bunch of stuff together and call all of the technical debt. However, looks to me like that’s a better phrase than anything else I’ve seen.
I’m curious what causes you to see maintenance as a metaphor?
I began my comment by pointing out that there is no direct mapping from common phrases to software construction. All models are broken in some way, some are just more or less useful than others.
The rest of my comment was trying out various phrases and then mapping them against how software is made. In a lot of ways, when we coders look at a piece of software? We only have two questions: does it do what it’s supposed to do? Does it need cleaning up? I understand that all of that sounds like the word maintenance to us.
The problem is that the phrase technical debt is being used for an audience wider than just programmers. So we have to ask ourselves what it’s trying to convey that maintenance doesn’t. The point here, as far as I can see, is to convey to everybody that it’s going to cost more to add features next time than it might. And that cost is going to increase, like accrued interest, the more we leave the code like that. It’s going to hurt, and it’s going to hurt you in the wallet.
The word maintenance sounds like normal activity that may or may not have a huge financial consequence down the road. The guy mowing the grass is performing maintenance. The guy sweeping the floors is performing maintenance. Yes, some kinds of maintenance like changing the oil in a car can lead to catastrophic costs later on if ignored. But other types of maintenance are quite optional. So while the word maintenance works for what the author is trying to say, it’s far too broad to share with anybody that doesn’t already have a really good sense of what good code looks like. In a way, oddly enough, the author is committing the same mistake as the phrase he is trying to analyze.
So when we use these inexact phrases, we’re left with a decision: do we want to emphasize that if you were a good coder you wouldn’t leave this mess? Or do we want to emphasize to you (and others) that by coding in a certain way you’re potentially causing a lot of cost down the road? I prefer the second. It tends to get people’s attention faster, and narrows down a lot of generic terminology to a more precise “Am I coding in such a way as to be considered responsible by other programmers and my customers?” That’s a journey we can start on and make a lot of headway. Otherwise we’re just stuck debating what good code is, what maintenance is as opposed to refactoring, and so forth.
Technical debt is very debt-like, I think of It as postponing costs today for costs later on. We avoid some costs in software design and development now, and pay interest in the form of lower productivity overall, until the debt is paid by putting effort in refactoring.
I think the metaphor only works in a facile way. That is, when you design and implement code, you can get it working fast, or you can get it working slow, but perhaps with a more robust set of internals (internal design, naming, decoupling, testing). If you choose to ship without the robust set of internals, you have done the equivalent of using a credit card to buy a big TV, rather than paying in cash savings. You can have the TV now (the user/customer can have your software now) but you still have to pay off the TV later (you’ll have to spend some time doing some refactoring work which might delay a future project). Spending debt in this way can be a good thing when your expectation is that the value of the user/customer having the software today is high, and the ability for you to “repay the debt” later is also high. It can be a bad trade when a software business decides to “put every purchase on its credit card” and to “never pay back any past purchase”.
I find that engineers sometimes use the metaphor this way, and in that case, it can be healthy. But I find a lot of engineers, perhaps the majority, use “technical debt” to refer to “any project the user can’t see”, so it captures a very wide range of projects – framework rewrites, devops infrastructure, backend schema changes, and so forth. When used this way, it just seems like a blanket justification for “internal non-customer-facing projects”, and thus loses its value and meaning as a term.
Meanwhile vb6 is running quite happily in hardware assisted virtualisation.
Technical debt is just some buzz word bingo from someone who has no idea what made mainframes popular when the 370 became famous for being able to run itself.
The only “debt” is that some aspect isn’t envogue at the moment , despite it working just fine.