Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Code Is Not Technical Debt (gavinhoward.com)
138 points by gavinhoward on Dec 21, 2023 | hide | past | favorite | 141 comments


Isn't it more useful to think of code not as an asset but as a liability? As in, instead of code being "produced", you "spend" lines of code when you solve a problem, i.e. "Getting X amount of business value cost us Y lines of code"?

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.


>Isn't it more useful to think of code not as an asset but as a liability?

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...


> The practice is pervaded by the reassuring illusion that programs are just devices like any others, the only difference admitted being that their manufacture might require a new type of craftsmen, viz. programmers. From there it is only a small step to measuring "programmer productivity" in terms of "number of lines of code produced per month". This is a very costly measuring unit because it encourages the writing of insipid code, but today I am less interested in how foolish a unit it is from even a pure business point of view. My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger.

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.


Although more lines _might_ situationally be better if it means the difference between a very clever but confusing one-liner versus a more verbose but comprehensible handful of lines. So like many things in engineering... it depends.


If you were advising an airplane manufacturer where production was tracked by weight, you might admonish them that they were putting airplane parts on the wrong side of the ledger. But later, after they changed their practices to stop encouraging the production of useless parts, the remaining airplane parts would be counted as assets, not liabilities. You, and they, would look back on the ledger comment as hyperbole.


> the remaining airplane parts would be counted as assets

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.


Most assets have costs associated with their ownership. So one might temporarily think about ownership in terms of liability as a reminder that those costs exist. However, you should then go back to using "asset" and "liability" in a way that people understand. Don't thank your collaborators for adding useful liabilities to your codebase.


While those airplane parts might be assets, they're still deprecating and have maintenance liabilities. Existing code might be an asset but it has costs to run and maintain.


well I consider it to be a metaphor for the maintenance required for the code. A piece of code 10 lines can be less of a maintenance problem as a oneliner if the latter achieves this via some needlessly esoteric technique.


> "lines of code" without context is a liability, more is not better.

Doesn't more lines == more features == more value.

How is that not better?


I don't think that equation holds.

More lines of code do not always mean more features.

More features do not always mean more value.


More lines does not equal more features! I just ripped out a bunch of unnecessary debug logging, the computation for that, unnecessary data copies, and then a 200 line method turned into 3 lines. What's more, the debug code had bugs I in it and would crash if it actually caught an exception.

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.


My first hundred lines in a module might be a feature but the next hundred lines in that module are likely handling unforeseen edge cases. My next -150 lines can be me refactoring the module to just be better designed.

Counting lines is a terrible metric for software. It lacks any sort of useful context.


if you adopt LoC as productivity metric then this is what you will get:

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.


> you'd have to start thinking of everything you own as a liability

Everything I own is a liability -- and an asset at the same time.


True in a blurry kind of way. Perhaps the word “net” clears up a lot here.

Some things are net assets, some things net liabilities.

The distinction matters a lot.


Maybe helpful to split into 2 parts: code functionality = asset, code maintenance & debugging = liability. So you must balance the 2.

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 is a depreciating asset which has maintenance costs.

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!


For the accounting nerds out there:

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.


> Isn't it more useful to think of code not as an asset but as a liability?

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.


That reminds me of SpaceX saying the most reliable part is no part at all!


Bumper sticker philosophies tend to have limited real-world utility.


I'm going to put this on a bumper sticker


Especially among programmers, who takes rule of thumbs way to literally.


Is it the sheer volume of code that bothers you or is it poorly organized in some way?


One of my key metrics when adding code to a system is how easy it is to rip out later. It's served me well so far.


> i.e. "Getting X amount of business value cost us Y lines of code"?

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?


It costs time to write the code, yes, but the liability of that code existing will cost an additional, unknown amount at some indeterminate time in the future.


Or that code existing will bring an additional, unknown at some indeterminate time in the future, cost savings when you go to implement a nearly identical feature and you find out you won't be needing to start from scratch as you already have all this well tested, named and organized code to pull from as you craft a new solution.

Your perspective just needs a shift from negative to positive.


I see that happen maybe one or two times a year, at most. Meanwhile I debug broken code literally every day.


The cost lies in the existing code’s implication on future maintenance and changes. You can’t measure that future time cost until it’s too late.


> Isn't it more useful to think of code not as an asset but as a liability?

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.


As I became senior, I realised that you always have that alternative course. It’s definitely a skill to avoid technical debt, even when you don’t have the knowledge at a given time. For example, if you code something in Spring and it seems that something is against the “Spring mindset”, then it’s almost 100% that you introduce technical debt. There was only one single time when Spring utterly broke its own methodologies, and it was needed for my day-to-day job (ie Spring Security with multiple providers). Looking after such cases is way more beneficial, than that one case when it took me a deep inspection of Spring to figure out, that there is really no nice solution.

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.


Teeth are liability in a similar way. Once we get the permanent set, they need to be maintained in various expensive and painful ways. On the plus side, they do provide value.

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...


Having worked on several large and complex codebases there is a very distinct difference in how the teams working on them saw the code based on whether or not it was unit tested.

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.


> 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.


Yes and no. Sometimes people try to write a short implementation to be clever (code golf) and the result is another liability.

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.


Equating technical debt to bad code does seem fairly common, but I think that that stems from what people think of as bad code. I feel that technical debt is commonly references in connection to writing some quick and dirty code that solves the immediate problem with little regard for the future. Code that is quick and dirty may feel like bad code, but it doesn't have to be. If your fix is good code though, doesn't that kinda mean that it's not quick and dirty and that it doesn't add any technical debt to a project?

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.


Technical debt is the difference between the actual code and how you would ideally write it with today’s knowledge and no time constraints. By that definition, bad code is a subset of technical debt, as you presumably wouldn’t write that bad code today unless maybe under time pressure. The other kind of technical debt is when you have in principle good code but the assumptions, requirements or external conditions have changed, and thus you wouldn’t write it that way today. Your second paragraph matches that case.


That’s a good way of putting it :)


The problem is in the mis-characterization that lines of code somehow equal better. Lines of Code(tm) is nothing but a measurement of how much effort it was to do, not how complex or how valuable. Just throwing that out there for the Erlang folks who produce very little lines of code but tremendous business value.


> Lines of Code(tm) is nothing but a measurement of how much effort it was to do

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.


> cost us Y lines of code

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.


This is where the distinction between essential/intrinsic and incidental/accidental complexity comes in. Any code in the solution but not required in the solution is excess. Usually though we don't measure this in lines, but rather in cognitive load (which can come in any number of inappropriate choices).


Ye sure. I know good code when I see it. The scale is very fuzzy, and others might disagree with my taste and we both are right.

"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.


I agree that it's a fuzzy scale. What I usually pick out isn't the amounts of stuff but how much of it either goes against the grain or piles on abstractions without a simplifying payoff (reduced cognitive load). Basically it comes down to picking the right set of abstractions (choosing your chunks/seams) and good naming since the factors which are being separated aren't vague.

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.


Often using a solution with many lines of code can be better, if it solves all the problems just by installing a finished product, even if it contains unnecessary parts, rather than a "keep it simple stupid" solution where you write only the needed parts yourself but have a lot more work to turn it into a tested and complete product. I don't use most of the protocols of my enterprise router but I won't write the routing protocols I need myself nor build a router myself, I just buy a router and ignore most of its features.


If the features of a product are properly decoupled from each other, you can get comparable results to the situation where they haven't been added at all.


That’s the kind of opportunity I’m looking for to introduce array languages to the codebase :^)


Imagine the horrors being fresh out of college and inherit some APL code with Perl as glue, that was made to meet some loc metric.


Honestly, the array languages are special in a way that the shortest solutions are usually also the most generalized solutions. I’d be more afraid of javascript or Python codebases that were built to minimize loc.


The functionality is an asset; the lines of code to produce the functionality can be considered a liability.

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".


Code is a liability does not imply more lines of code is more liability. You can owe 1000 dollars to one neighbor and 1 dollar each to 100 neighbors. The number of neighbors you owe money to is not the right metric for how much liability you have. But it's still wrong to say that owing 13 cents to your best friend is not a liability


Think of lines of code as parts in a mechanical assembly. Not all parts are the same, obviously. But a design with fewer parts will probably be cheaper and more reliable than a design with more parts.


I think of "technical debt" in the same way that I do construction scaffolding: it's essential, but if you focus only on your scaffolding then you won't build the building you're trying to build. If you never take the scaffolding down, then it becomes part of the whole project. If your scaffolding is poorly done, then your building (program) will crash or will take forever to build. Lots of potential to build proper scaffolding that vastly reduces the cost of a project.

Can't be done without it, but it can definitely get in the way.


> Isn't it more useful to think of code not as an asset but as a liability?

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.


The biggest mind bend you can give yourself here is that the difference between asset and liability is largely perspective only. Consider your deposit in a bank. It is, by definition an asset. However, it is also, by definition, recorded as a liability for the bank. They both lend against it, as an asset, and they are required to pay it back, as a liability.

That is, yes. Code is a liability. This does not keep it from being an asset, as well.


> Isn't it more useful to think of code not as an asset but as a liability?

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.


All bad code is tech debt, but not in the sense that it was consciously chosen. We usually only talk about the cases that currently limit progress/quality. The interest rate varies on where that bad code lives and how cumbersome it is to work with. If it's in an area with frequent changes that are incidentally difficult to implement, then it's high on the tech debt list.


The first time I heard the time 'technical debt' was during a discussion on software related activities to fixing something that is not a bug or a feature which are usually the two main categories that the product owner cares. You meet your deadlines and the customer is elated with the software/product, then 'technical debt' is the whatever bucket.


So the analogy become: Capabilities/functionality is "assets", code is "liability"? (or maybe "perfect" code is closer to equity)

Just as "real" assets depreciate, capabilities/functionality can as well. Require both maintenance and has a operation cost (also beyond hardware cost).


I think I see the disconnect. People who can read code, don't see it as a liability, but an extremely valuable asset. People who can't read code, however, only see it as a liability. The value to them is in the compiled binary because that is what they know how to interface with.


> lines of code

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 both!

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.


one wonders when code will be thought of as ... code.


Having recently gone to a bit of trouble to learn the basics of accounting, I have found it to be quite a useful system. It seems that most commenters here do not understand that system, or what "assets" and "liabilities" are in accounting terms. Assets are stuff you have. Liabilities are expenses that you are expected to owe in the future. Debt is a specific kind of liability associated with repaying loans. There are other liabilities, like maintenance costs, that are not debt. So I agree with the post: there can be liabilities associated with code, but code itself is an asset, according to any sane accounting metaphor at least. Of course (as the post also clarifies), the value of the asset depends on how well it serves a purpose, not how much of it there is or whatever. And its value may in some cases be less than the liabilities (maintenance costs etc) that you owe on it. Nevertheless, it is an asset, a thing you have, with some positive value.

(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.)


A notable difference is the liabilities usually have a due date, while technical debt usually have none.

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?


Wouldn’t the due date just be business deadlines in this analogy?


Well no, presumably we usually accumulate technical debt to meet the business deadline, with the hope of getting rid of it later on.


Thank you. Would houses be the most prolific example? ie: they function as an asset, but also as a liability re: maintenance, disaster, market trends.


The house is a good example, but it's worth being careful: the point is that the house is not a liability. There are liabilities associated with it, starting with repayment of the loan that you used to buy the house (for most people), but also maintenance, insurance, taxes, etc.


Really glad to see this rebuttal. I understand the sentiment behind the post from the other day, and most days when I look at the repos I work on, I feel the same way, but it just isn't true in a general sense. We write code because it is _bottom-line_, valuable as fuck. It really boils down to: time is the most expensive asset around.

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)


> 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)

According to Joel Spolsky, it's something you should never do[1].

[1]: https://www.joelonsoftware.com/2000/04/06/things-you-should-...


In my experience, the urge to refactor everything stems from one or a few really really badly coded features that waft their smell to the rest of the codebase.

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.


And as with all things, "Never" actually means "Sometimes but extremely rarely".


Liking this post, thanks for sharing.


If I have the time to plan ahead, I much prefer to prepare with a full test suite that I fan rely on before considering a rewrite.

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.


Imo the only time you should do this is when you need features/upgrades that the current paradigm doesn’t support, the existing project is well tested, and the “rewrite” can be done in successive smaller changesets which don’t break everything.


This debate feels like arguing whether real estate is debt or not.

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.)


I like the analogy with real estate. It has that intrinsic decay element that large systems also suffer from. It also incorporates the "death by 1000 cuts" experience of dealing with a nonstop slew of minor problems week-by-week. In this analogy, I think you could compare vendors like Amazon and Microsoft to Blackstone. Scale is what makes the game work for these players. Very few get wealthy by personally lording over a handful of concerns in a single metro.

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.


Renting is fragile. The landlord decides how long you may stay. Ownership means being in control. I store things I like on my hard drives so I don't lose them when someone else decides it should no longer be available on the Internet .


Hard disagree.

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.


How about we start thinking about Org debt. All organizations become debt at the end of the day, you know, because suits die. Fortunately, we end up moving industry norms, which allow the new suits to eliminate that org debt, temporarily. Maybe someday, we can eliminate orgs all together.


Modeling code as an asset rather than a liability could create a certain culture that drives you off a cliff.

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


This feels in line with TFA to me. The value of your assets were underwater (their liability exceeded their value) because they didn’t match the problem domain of your business. You’ve now jettisoned those liabilities and are focusing solely on the assets that are valuable, because they match up well to the problems you need to solve.


The fact that it's an asset doesn't mean its value is proportional to the number of lines that are there. Similarly a house is an asset, but not all 1000 sq ft houses are worth the same amount of money.


I just want to +1 this because I had mixed feelings about the last post this one addresses and some of the comments made me feel a little insane and I couldn’t figure out why.

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 like the analogy that code is like weight to an airplane (“Measuring programming progress by lines of code is like measuring aircraft building progress by weight” - Bill Gates). You want enough code to achieve your business objectives but no more since code carries a maintenance cost.

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


Always liked Reinertsen’s post on reframing tech debt to deferred work.

“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...


Both authors are somewhat wrong, and both authors are somewhat talking about different things (and thus talking past each other).

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).


> Gavin here is talking about the development of system software, where the requirements are perfectly clear, rarely change

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.


I wasn't saying the requirements never change. But the frequency and extent of those changes is simply not comparable to the frequency and extent in business software. The features of your `bc` implementation may change, but fundamentally it will always be a command-line calculator. It isn't tomorrow going to need to become Wolfram Alpha.


Fair enough.

Though, to my ears, that just sounds like minimizing code liability is more important in that context.


These endless conversations about what “tech debt” is reveal how poorly matched the term is.

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.


There are several links that 404 at the time of writing this comment, so maybe this person has more technical debt than they realize?[1]

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”?

[1] https://gavinhoward.com/img/bc_stack_plot.png


I'm sorry! The files exist, but my upload didn't grab them.

Fixed now.


Thanks for updating! Sorry for being a little cheeky about it!


I deserved it. :)


I'm currently getting nginx 404s on the git of Thesueus links, fyi.


I'm sorry! It's fixed now, but for some reason, those images were not uploaded even though they existed.


Maybe it's a scale thing. If you are sologeneer working on your own project, with a singular vision, making tools to make your life simpler is a no-brainer.

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.


this debate reminds of kitchen appliances. what makes an appliance a burden or not is how much cognitive load is takes (space taken, where is it stored, how to take apart and clean, how to use, etc..)

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


I think one nuance that is missing here is what "product" means. In the most broad sense, tools such as bc and dc are indeed products. However, I think the discussion of technical debt tends to focus more around larger scale products created by commercial development teams. That certainly affects the nature of technical debt.


Small comment for the author as I'm currently reading, the survival plots end up in 404. Interested to see those though.


I apologize! Those plots are there now. My upload did not grab those images even though I had them.

And I didn't check because it was past midnight.


Code ain’t code though. Production tested library code is an asset. Known good code from old projects that can be used as reference or easily adapted to new projects is an asset. Project specific glue code is a liability. Streaming mounds of hacked together prototype or testing code are technical debt.


> The post is “All Code Is Technical Debt” written by Paul McMahon. And everything is just slightly wrong, starting from the title. So let’s break it down.

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.


I was thinking it should have been called "My Code Is Not Technical Debt."

It still defeats the "all code" claim, though.


Bob's code is technical debt. Fuck that guy.


With AI, I'm less concerned about the sore parts of the app than previously. Waiting for better versions should lower the cost to address it even further.

Probably not the most professional way to think about it but it seems like this will be the case.


Code being technical debt is trivially false. Code is an asset. A house is an asset. A house falls apart if not maintained. So does code. That doesn’t make a house debt, nor code.


Code is an asset once proven to be so.

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.


Software is the asset, not code. A pile of bricks metal plastic and wood is not the asset, the house someone can live in is


Blueprints for good houses are assets, that is what code for good programs is.


Technical debt isn't limited to maintenance. It's like if a two story house was built on dirt instead of a proper foundation. Or you skipped adding insulation, or you didn't put all the plumbing in.


And yet, not every assortment of bricks and wood in a backyard is necessarily a house. It must be turned into a house with accepted value first, until then it might even be a liability to the real estate it is piled on.

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.


I think I like the liability word. Code can be a liability and an asset.

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.


What's the difference between debt and investment(asset)?

You won't know until later.


I'd rather have technical debt than actual debt, personally.


A sufficiently jaded software engineer can even think of technical debt as an asset. It's job security.


I code, therefore I am


In a way, its kinda like financial debt where if the monthly payments on principal/interest are not too bad, I'd rather not refinance.


If code is a good abstraction, it's a valuable asset.

Else, it's a liability.


I often think how every headline on HN could be inverted into its 180 degree opposite and it would get as many upvotes.

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.


Maybe stop reading the titles as a statement of 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.


When a headline is written as a fact, I see it as a fact.

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.


that's a you problem.


There is in fact, no problem at all


I too generally post rants on things I don't consider to be a problem...


Author here.

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.


> is my mental model

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


My mental model is still a fact in that it exists.

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.


Yes, that is obviously true. Both points.

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


[flagged]


Lol this is funny because many years ago I owned one of the largest viral sites that got billions of visits per year, and then sold it, before clickbait became popular, during its rise, and then during its fall.

In fact I've written tools in the past to analyze virility of headlines (around ~20,000 of them)

This is all beside the point... because my original comment wasn't about trying to go viral and get views.. that is easy. It was not being extremely fucking unoriginal.


[flagged]


I didn't stop when it became a thing, I stopped after running the site for over 5 years and algorithms changed and it became more of an adops arbitrage opportunity than actually "going viral." The occurance rate of true virility dropped orders of magnitude once everyone started leveraging the same headlines, etc.

I'll read your post


> I stopped after running the site for over 5 years and algorithms changed

That's exactly when it became a thing because algorithms are 50% of the reason stuff goes viral or not.

> it became more of an adops arbitrage opportunity than actually "going viral."

If you did run a site, I think I could believe this too.


I think you're thinking I'm doubting some ability you have to go viral, I'm not even talking about that at all. I never was, I just brought it up because you made some point like "just be sure you go viral as well", and it was a curious (hilarious) thought that I owned one of the largest viral sites.

My original comment was really simply just about....... giving your writing the headline it deserves, one that highlights your unique perspective/life experience, one draws me in. Shows me some curious aspect about your perspective I can learn from

Thats' what I want to read, not another garbage in garbage out bullshit headline.

But do your thang


No, I'll pass. But you're welcome to not believe me.


Then I have no choice but to believe that you are lying.


Once again, this is a very unoriginal take.

i realize it's the internet, people lie, blah blah. But not everything out of the ordinary is a lie. Consider for a moment it's true.

The amount of people that just immediately reject something with the answer "prove it or you're lying", this in itself is such a basic idea, its surface level, 1 dimensional layer of thought. Try to read between the lines, because you are basically closing your mind off to thousands of potential factors, this complex web of cause and effect, and immediately rejecting some idea out of the gate simply because .... I don't name something?

At even the most simplest of levels, your method of thinking doesn't even work. I could just lie, I could say I owned X site, and X tool. I could literally google in 2-3 mins, find a random viral site from the time period I'm talking about, and then some tool similar to buzzsumo, and I could say "yes I built that"

IMO - Life is far better with an open mind by default, than a closed one

Just because I said your headline is unoriginal as shit doesn't mean you have to rubber band reflex the other direction that "I MUST BE A LIAR!!!" as the only explanation.


> Just because I said your headline is unoriginal...doesn't mean you have to rubber band reflex the other direction that "I MUST BE A LIAR!!!" as the only explanation.

I only got to that point when you gave a claim you would not back up, not because of your "headline is unoriginal" opinion.

To answer your opinion, look at my archive [1]. I have some original titles:

* "Your Loved Ones Are Prisoners, and You Made the Chain"

* "The Scourge of 00UB"

* "Head in the Hurricane: Securing a Web Server"

The one thing those headlines have in common is that they did not go viral.

Sure, a headline may be unoriginal, but if it gets more people to read it than an original headline does, why wouldn't I do that? I think my writing deserves reading more thwn it deserves original headlines.

[1]: https://gavinhoward.com/archive/




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: