Code Is Not Technical Debt
gavinhoward.com
gavinhoward.com
As for the phrase "technical debt": While I like the metaphor, in my experience, most people use it as a synonym for "bad code", so I recommend making sure everyone agrees on the same definition before using it.
it's not the lines of code that costs, but time. It may be OK to use lines of code as proxy for time spent - but that sort of assumes that each line took similar amounts of time to write. I am not sure that's really the case, but even if it is, hiring somebody more competent will get more lines in less time!
Therefore, why not just measure the time directly?
Your perspective just needs a shift from negative to positive.
In my view yes. I often find it frustrating how much code people will generate to solve a problem that occurs extremely rarely and the consequences are not severe anyway. All of that code is now a liability and must continue to cope with any future changes to the system. No matter how elegantly you think you write code, the easiest code to change is the code that doesn't exist at all.
But... if you do the same thing in fewer lines, by writing terser code, that may be harder to understand and therefore maintain, and that's also a liability - maybe more of a liability.
If lines of code are a liability, some lines of code are much more so, because they are hard to understand, overengineered, badly designed, brittle, or probably several other reasons. Code is a liability; bad code is far more so. Get the most assets - functionality - with the least cost - lines of code plus "things that make code more expensive".
If you measure cost by lines of code, you'll get programs like this: https://www.youtube.com/watch?v=a9xAKttWgP4&t=402s
It's not even that. There are certainly low-effort projects that take a lot of lines of code, and there are high-effort projects that take few.
I like the garden analogy. We want a garden to be pleasant and nice, but we'd also like it to be easy to maintain. A successful garden is about finding that balance between plants that mostly take care of themselves and a few unique things that might take a bit more care but make the garden special. Daffodils require no maintenance at all but they only appear briefly and everyone has them. A garden full of daffodils isn't special.
Software is there to be useful, to provide some business value. But it can't all be boring old daffodils. There has to be something your business is doing that is different from any other business, otherwise why are you even writing software? So, yes, there is a liability in the sense that you need to tend to whatever garden you decide to grow, but there is a definite asset in the sense that it is delivering value to the business. It's all about trying to manage the size of the liability given the size of the asset.
Yes. I love to code and I love that metaphor. One day while browsing Reddit/TIFU, a post jumped at me: "TIFU by creating and releasing a Reddit plugin for Firefox/Chrome, because I'll have to maintain it for my whole life."
It's so funny, true and enlightening at the same time.
> most people use it as a synonym for "bad code"
For me, "tech debt" is the suboptimal solution you shoehorned in the last minute because you don't have any alternative course at that moment (time, brain fog, etc.), which can boil to bad code, in general.
Presence of code itself is not the technical debt itself.
Nowadays it’s even easier with LLMs, they can help you point to the right direction, then it’s easy to validate with some search engines.
Code should
1. Function as needed 2. Be clear to read and understand 3. Perform well enough
Possibly even in the order listed. Performance is the trickiest one of course. Sometimes it's not negotiable and messes with #2. But one should always benchmark and profile to see what needs to actually be done before sacrificing clarity and cleanness.
Rushing out poorly architected and implemented software systems means that the asset depreciates at a much greater rate than otherwise, just like a crappy vacuum cleaner.
Since we’re mainly in the business of building a single self-updating vacuum cleaner per business we’re fully capable of taking a cheap design and a cheap implementation and making it better over time… at a cost!
We've got an asset account, and a couple of expense accounts, depreciation and maintenance. So the depreciation transactions are from some kind of assessment of the asset's value over the full lifetime (read: will anyone still use this Android app in 10 years?) while the maintenance transactions are from the actual costs to keep the asset operational.
Depreciation isn't really about quality or value, rather lifetime expectation. As a consumer buying a cheap vacuum cleaner you are knowingly buying a product that depreciates at a higher rate. You can maintain that vacuum cleaner for a lifetime if you wish but those are separate expenses.
So in terms of software, if you should be rushing something out the door in order to try and find product-market fit, do so with the knowledge that you are creating an asset with a shortened expected lifetime, ie, that depreciates at a higher rate. As you transition from prototype to a more robust system you adjust the rate the depreciation to match.
You can choose to keep maintaining the prototype but the costs of doing so are probably more than the enhancement costs that are offset by increased capitalization. But again, do you expect anyone to be using your Android app in 10 years?
The accounting practices in software are much different than thinking about a widget factory so I do get the sense we could using some innovation in the field.
Architectural decisions may very well result in technical debt, but an architectural decision to go with a vertically scaling solution doesn't have to be a bad decision or bad code. It's only really a problem once you get enough users that you need to start scaling horizontally. At that point though it would very much be considered a technical debt since it was originally trading development time with future scalability.
In the same way a factory should be accounted for as a liability. You spend to build the factory, then it depreciates to zero value, so all you've done is lose your original capital. It's not possible to ever get ahead.
That's just a very bad understanding of basic accounting.
Code is a capital asset. Getting value from it over the long term requires maintenance and repairs, improvements and replacements. "Technical debt" is a complete misnomer in terms of accounting principles.
Can't be done without it, but it can definitely get in the way.
Just as "real" assets depreciate, capabilities/functionality can as well. Require both maintenance and has a operation cost (also beyond hardware cost).
No, it is not. For consistency, you'd have to start thinking of everything you own as a liability, and only use "asset" to refer to a problem solved by something you own. This would be confusing to everyone you talk with about assets and liabilities. On a day when you didn't drive anywhere, you'd point at your car and say "I got no assets from this liability today." (There would be some truth in that statement, but your listeners would definitely be confused.)
EDIT: I should add, I believe Dijkstra was using hyperbole to make a point with the "lines spent" part of https://www.cs.utexas.edu/~EWD/transcriptions/EWD10xx/EWD103...
It doesn't sound like hyperbole to me. "lines of code" without context is a liability, more is not better. The correct side of the ledger is being stated as liability, if we're to consider lines of code at all.
I'm not in the industry so can't say, but the weight of parts is always a liability as it contributes to fuel consumption. Parts also require maintenance (but not necessarily by weight).
An operational plane as a whole is certainly an asset. Perhaps this is how we should handle software, the whole is an asset, the quantity of parts that need maintenance are liabilities.
Doesn't more lines == more features == more value.
How is that not better?
More lines of code do not always mean more features.
More features do not always mean more value.
Counting lines is a terrible metric for software. It lacks any sort of useful context.
first 6 months: more LoC => more features next 6 months: more LoC => less features next 6 months: more LoC => 1 feature next 6 months: more LoC => some existing features not working well
and so on
because a new feature is not only adding code but changing code.
and the more code you have the more you have to change it.
To my knowledge researchers have not found a single metric that correlates with bug count other than total lines of code. Unit testing, developer experience, none of it is predictive of bug count, only size of code base has a correlation.
Everything I own is a liability -- and an asset at the same time.
Some things are net assets, some things net liabilities.
The distinction matters a lot.
Writing less code minimizes the liability side. Combined with a "YAGNI" stance, you can minimize your codebase total liability while writing the least amount of code required to do the job.
Software rots too, if for no other reason then due to Lehman's 1st law [1]. Difference is that with code we have more choices.
[1] https://en.wikipedia.org/wiki/Lehman%27s_laws_of_software_ev...
I don't like these rules of thumb that when taking literally screws us. Some manager is going to want to minimize locs now.
Code suckiness per feature is a qualitative measurement. I don't think there should be any allusion of absolute numerical scores for that property.
"Cognitive load" has to be normalized by "stuff done".
I mean the unit is something like: (stuff done by app) / (code stuff) where 'code stuff' is really really fuzzy. I mean dependencies count into that measure, even though they are zero loc written by you. Etc.
Few things are 50/50--those cases rather tend to be "no one really knows yet".
My phrasing is "you'll know good code when it's shown to you" where "you" is myself for my own work.
The teams who were fastidious with their unit and automation testing saw the code as an asset. It was generally reliable and not risky to change.
The teams with little to no unit or automation testing saw their code as an ever growing liability as complexity increased ultimately culminating in the great rewrite every few years.
Damn! I'm fortunate to have never experienced this. In my entire career, only once have I seen a project suffer from a complete rewrite, even with projects that did no unit testing.
That is, yes. Code is a liability. This does not keep it from being an asset, as well.
If we're thinking in these terms, code is clearly both an asset and a liability.
I don't think of code in those terms at all, though. I think of code in terms of change. Changing code brings risk and expense, and that's why the rule of thumb is to never touch an existing line of code without careful consideration and a very good reason to do so.
(Whether to call the liabilities debt in this metaphor depends on whether it makes sense to say you took out a loan. Maybe in some very abstract sense it works, but it is a bit of a stretch imo. I guess its a nice metaphor because it connects to the idea of why you might want to take out a loan, e.g. because it will help you develop more future income than the cost of the loan. Regardless, even if you want to call it "technical debt", the code would be an asset that you have purchased with the borrowed funds. The debt is what you now owe associated with the loan of those funds.)
Just a though: would assigning a due date to properly refactor the shortcuts we sometimes have to take be a useful exercise to better evaluate the trade off and help it not accumulate too much debt over time?
This debate does bring up a very interesting thing though: At what point do you ditch the old code and re-write the whole damn thing? (I am currently struggling with this)
Rewrites are difficult to estimate, difficult to pull off, and often demotivating as the work drags on. Having a suite of test coverage that I can reuse for the rewrite both gives me an easy check to make sure functionality isn't lost and a cheap bit of motivation as I see tests slowly turning green.
According to Joel Spolsky, it's something you should never do[1].
[1]: https://www.joelonsoftware.com/2000/04/06/things-you-should-...
The limited from-scratch refactor can be painful in the short term, but after it’s done you realize how much more manageable other features are because you’re no longer mentally burdened by the worst of the codebase.
It can certainly be that way if you're leveraged to the max, the value of the property has gone down, and you're paying for maintenance. Then you're just losing money on the property. But ideally and commonly real estate is an asset with equity value.
It's largely the same with code. It can be a liability, but it should be an asset. And if you don't want that risk on your books, there are increasingly many ways to rent code (SaaS / PaaS / etc.)
Our model today is to rent out complexity & infra as much as possible. We don't want to own a single square foot of tech property if we can avoid it. We don't even have physical floor space in our corporate "office".
We aren't particularly interested in the construction style or the brand of the lighting fixtures. We just want some kind of generic, air-conditioned box w/ WiFi to exist inside of while we conduct our actual business. The shorter & more flexible the lease terms, the better. If we could, we'd like to pay per minute of occupancy and only while we are on the property. That would be most ideal.
Greenfield vs Brownfield experience teaches us differently, you don't need analytics involved. Scope creep doesn't just eat up man hours, it eats up the ability to maintain and bring onboard new people. Learning new features to you doesn't eat your time when you already know the product. Learning new features as newguy is far harder because you don't know the underlying product, but you're expected to know the core product, including all new features.
This is tech debt, and all code becomes it, because devs die. Fortunately we end up moving techstacks, which allow the new devs to eliminate that code debt, temporarily.
You see this same thing in gaming. Dota 2, LoL, CS, Live Service XYZ are not getting new players because the amount of things you have to learn now vs when the game was new is mountanic.
When we were looking at code as an asset, we had lots of microservices and sophisticated contracts between them. We advertised this as some kind of inherent product value (it wasn't).
Only once we started thinking about code as a liability did we begin making serious progress with our customers relative to our roadmap.
We do very little in-house code beyond our core product these days. We got away from custom admin web tools, microservices, fancy SQL, etc.
Everything you have to think about is technical debt to me. If you are mentally preoccupied with A, you aren't thinking much about B, C or D. Fewer moving pieces doesn't always mean less code, but it usually does. This also gets into "innovation tokens", etc
I can’t think of many times in my career where adding or modifying code made things more difficult, it’s easier the more I put into it, the more I reason through it and make improvements or add features. When I read this post it makes more sense to me, of course I would program this way, because I am very lazy and I don’t like programming for the heck of it, I like building, so any programming that got in the way of me moving faster became an obstacle to be improved or removed if it couldn’t.
This is the natural progression of good systems I’ve seen so far in my relatively short experience programming/building (about 11 years if you add school).
Anyway thanks for this, I thought I was going crazy. Need to go reread pragmatic programmer again.
I suppose you could say the net value of some code = contribution to business objective - maintenance cost.
This also implies that code could have a negative value depending on its business value and maintenance cost
“When we refer to postponed work as technical debt this automatically biases us to assume that both ongoing and future costs are more certain than they really are. This, in turn, causes us to overestimate these costs, leading us to be overly cautious about deferring work. If it is your intention to bias the decision against postponement, this is clearly the best term to use. However, if you are trying to carefully weigh of pros and cons of postponing work, I’d recommend using a more neutral term like deferred work.”
http://reinertsenassociates.com/technical-debt-adding-math-m...
Gavin here is talking about the development of system software, where the requirements are perfectly clear, rarely change (unless somehow the underlying system changes), and that he is working on almost entirely by himself. And he's taking conclusions from that and applying them to business software, where the requirements are complex, rarely clear, change weekly in often unpredictable ways, and the development team is large and constantly changing over time (as people leave the company and new people come in).
This leads Gavin to conclude it is his own cleverness which keeps his code free of tech debt. Phrases like this give away the confusion:
> I also do one more thing that almost no developer does: I actually design my code before I ever start coding.
This is all well and good! Until you realize in a few months that the business is going in a new direction, and your big beautiful design is now based on a set of faulty assumptions. You either go back to the drawing board (and lose the business time and money) or those new features are going to be bolted on as ugly hacks. (You might even convince yourself "we'll eventually come back and refactor this, surely." Ha!)
As for the original author, his mistake was ascribing causation to a correlation. Since all projects he's ever seen that grow in code size gradually accumulate tech debt, he concluded that it is the increase in code size which caused the tech debt. But in reality - Gavin was correct on this point - programming is about developing a mental model for the solution space. Debt arises when the developers no longer possess an accurate model (which they very often don't, when the model they possess is based on a set of vague requirements, and/or when the model that was correct three months ago is now wrong since the business made some new decisions, and/or when the developers who had an accurate mental model when they were working on the problem three years ago have now left the company and the new team don't possess all of the knowledge and context of that era, et cetera et cetera).
This is not true.
I've had requirements change on me before, and I alluded to this with one tiny phrase:
> It can happen in two ways: the problem changes (your liability increases) or your software becomes less useful (your asset depreciates).
(Emphasis added.)
Code liability is directly tied to both the code and the problem. If the problem changes, including requirements, your liability increases.
I still suggest that people design though; the act of doing so sometimes reveals flaws and ambiguity that can be worked through early, even if only partially. And design does help keep your mental model more correct.
Though, to my ears, that just sounds like minimizing code liability is more important in that context.
Debt is not something useless. Or malformed. It is something you owe.
If you sign a contract to produce a feature and get paid up front you have tech debt. Literally.
To pay off the owed feature, you produce & ship the feature.
If you throw out some feature quickly in a haphazard or buggy way that requires maintenance to operate as advertised (regular manual fixes of data base corruption), you now have operational debt. Literally.
To pay off that owed operational commitment, you can fix your bug or keep fixing its impact. Pay off all at once, or for all time.
But if you ship a fully functioning feature that works, regardless of its implementation, you don’t owe anything.
If the feature had a haphazard design or implementation that is going to slow future development, you have taken a shortcut and reduced the quality of your foundation.
Reducing the quality of a foundation due to a shoddy code rework isn’t debt. You don’t owe anything.
It’s a destruction of present net value.
Present net value is your codes immediate value + its expected contribution to future value.
Maintain and increase the “present net value” of your code base by making changes carefully, and investing in its ability to fit future needs.
Regardless, my mental model is quickly becoming to ignore anyone talking about “technical debt”. Where’s next week’s blog “All blog posts about technical debt are technical debt”?
Fixed now.
If you are implementing a feature for stakeholders on a large piece enterprise software, you don't necessarily have knowledge or understanding of helper tools from earlier work, so that's extra overhead to understand anything non-standard. Then when the stakeholders change direction (as they often do), any assumptions in your code may need to be upheld while implementing the next feature.
Edit: This is also why it's nice to use widely adopted libraries and frameworks for any helper code. That way a new starter has a chance of understanding what's going on.
and how much value it provides. (time saved, quality produced, aesthetics)
sometimes it's "debt" when it costs more than it's value produced but this is can be highly dependent on how often it's used. (space taken is a large fixed cost)
with code, the space is "infinite" so there's a lot of clutter like "pineapple corer for those with a diameter between 5cm and 10m, corer for those with exactly 12cm, bannana nutella injector, etc.."
combine this tension with a changing environment and output requirements (one week steakhouse, next is chinese food, etc...) and everything starts to feel like a pile of crap
going "smaller" alleviates this problem b/c a lot of specialized tools are designed for scale. one steak and one chow mein doesn't justify a salamander broiler or a wok
And I didn't check because it was past midnight.
Similarly this post's title seems a bit off. If it was "Only some code is tech debt" we would have less disagreement in the comments.
It still defeats the "all code" claim, though.
Probably not the most professional way to think about it but it seems like this will be the case.
You won't know until later.
I don't get the obsession with trying to condense this down to a single concept.
Code is necessary, sometimes we write good code that turns out to be an asset in both the short and long terms, sometimes we write mediocre code which is a short-term asset to our business goals but in the long term turns out to be debt. Sometimes we write bad code that will probably never justify itself as an asset because of the problems it a) causes and b) requires human intervention to support, patch or delete.
Same applies to code. Also code should first be proven to create value to be valued as an asset. In worst case, it may just be a pile of bricks devaluing the property.
It can be an asset because it solves A, but it can also be a liability because it makes it hard to implement B and C.
A house can be a liability too if you're required to pay for public services, for example. Sure it's an asset too, but like code, the liability-side might make it worthwhile to get rid of.
Else, it's a liability.
I often also think its crazy how people are painfully unaware of this fact... I swear these have got to be the stupidest headlines, and yet people don't seem to ever have an original thought about it, just for a fraction of a moment..... a moment of awareness that shows them that their factually stated headline is actually 100% not a fact.
I certainly didn't interpret it that way, your statement is obvious enough that it immediately turns the headline into a strongly held opinion.
I refuse to read uncreative factually written headlines as any other way, as its basically attempting to spoon feed the reader into some basic idea.
This is in a similar way to how CNN or popular news stations talk to you as if you are a 5th grader.
I read headlines as they're written, and creative headlines get my attention, and stupid headlines go into the waste bin of all the other stupid headlines stated as facts which are not facts.
It is 100% a fact, not because code is or isn't an asset in the financial sense, but because "code is an asset" is my mental model that I think could help others.
You cannot say that my mental model is not a fact; only I can say that.
Also, if you don't think it's a good model, you should argue why instead of just saying I'm wrong with no substance.
Exact proof what what I'm saying. Your mental model isn't a "fact" it is a perception group of beliefs.
A red ball is red is a fact.
"all code is technical debt" is a stupidly worded headline as if its a fact, when it is absolutely nothing more than a useless opinion in a sea of a million contradicting other opinions that say the opposite.
Instead, a headline can be worded to not be stupid by not attempting to write it as a fact, but as the ACTUAL benefit, or ACTUAL point being made...
Your perspective is unique, special, in makes you different. Share THAT, emphasize THAT. dont water it down with stupid genericness.
The original title by Paul McMahon is equally as stupid as this one
Yet, people keep doing it, over, and over, ad nauseum. I think people just simply don't realize how unoriginal they are, its like do they have even a fraction of awareness to try to be different?
Your headline is how you captivate people, actually try to state the intent/purpose so it's useful, to get into the mind of the person reading.
Not to use a hammer trying to clean some fine china.
"Keeping my projects maintainable by thinking about them differently" or something, literally anything. I didnt look at your article except skimming, and this is an off the cuff idea in 1 second, but you get the idea. It's something that the reader sees as a benefit, or something nuanced that they can learn... some part of your perspective they can integrate... not some basic-level statement of fact they're going to immediately agree/disagree with... as if this is your only tool in your toolbox to get attention or build curiosity
In addition, headlines do have to be kinda clickbaity to get traction.
Also, your "skim" was hardly even that considering I put useful summaries at the beginning and end. Read the one at the end.
The problem lies in presenting your fact to other people.
Theres a very surface level way to do it which is "me fact. smash fact into ur hed. now ur fact. gronk smash"
Another is to actually attempt to be persuasive, to build curiosity, to let the reader step in for a moment into your mind, where they can pick up a gem they might not have in their own life experience, and directly apply it. What does this person know that i do not? what is he considering that i am not?
Its a subtle approach, that is nuanced.
It isnt extremely blunt, as if your only way to build curiosity is to state blunt facts as truths, hoping that people either agree and click to validate opinions, or disagree and generate a bunch of comments saying "youre wrong".
This in itself wouldn't be so bad, but its just legitimately the most NOT creative, MOST generic way to do it. It's the "salt" of headlines. If any person has any self respect for their writing I suspect they wouldn't want to serve the most important meal of their lifetime using the only ingredient as salt.
You can just look at the huge swaths, oceanic waves of generic "THIS IS A FACT" headlines. Its so fucking painful at this point, that I immediately reject them in the same way that I reject ads and news.
It has nothing to do with the person's actual opinion, it has nothing to do with even the fact that the headline is written as a fact (which in itself is a useful device sometimes), its that 10 million other headlines do it. It's like the lowest form of headline, and it is as unoriginal as it gets. and THAT is what painful, unoriginal people being unoriginal yet still doing it. Perhaps they do not care, I do not know.
There are absolutely better/more creative ways to build curiosity though.
A good example is viral youtube videos... I can't think of any viral youtube headlines that are written in this way. A good headline takes serious thought and creativity. Imagine if every youtube video was just stated as "Code is Not Technical debt", and the next video "code is technical debt" and the next video "code is life" and the next video "code is death"......... super yawn