Hacker News new | ask | show | jobs
by mannykannot 1786 days ago
Well, I did what the author suggested, and wrote down my definition. After a short internal dialog, I came up with this:

"Technical debt is the burden that implementation choices may place on future development."

Nothing in the article leads me to think that this is either incoherent or irrelevant.

With regard to its coherence, I say that it is empirically verified: it actually happens!

The claim that it is not technical because it has consequences beyond the technical is a non-sequitur. Just about everything we do that is 'technical' has implications and consequences that go beyond the technical: The mere fact that most of the technical things we choose to do are done for non-technical reasons is enough to establish that. The root cause of a problem and its broad consequences are separable concerns.

This formulation avoids the objection that its only debt if it is paid back in the same form as it taken out, but that was a tendentious claim anyway - it is completely reasonable to consider the situation where, say, I give a farmer cash in return for some produce at harvest time to be a debt. If we are going to be pedantic, the author might as well say that technical debt is not debt because it is not an exchange of money. Arguing over dictionary definitions is not going to lead to anything useful in this matter.

10 comments

There are two quotes from Cunningham in there:

A little debt speeds development so long as it is paid back promptly with a rewrite. Objects make the cost of this transaction tolerable. The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt.

>> Cunningham disliked the notion that technical debt signified “doing a poor job now and a better one later.” This was never his intention.

You can split hairs of weather code was poorly written vs written from an underdeveloped understanding of the problem, but the effect is the same. People have to deal with suboptimal design decisions repeatedly until they are corrected. To extend the debt/interest metaphore, these poor decisions also undergo compounding if not paid back.

I am someone else who apparently never understood what technical debt was supposed to mean.

I've always assumed engineers (myself included) write code to the best of their abilities to solve a given problem at the time. But we all know that, over time, features and such get added to the code base and it is stretched beyond what it was originally meant to do.

That the code base would should be refactored to better accommodate these new features that have been glommed on is the tech debt. There was nothing poor about the original implementation and the additional features were added with the understanding that the code could not be rewritten from scratch.

I may be splitting hairs here but I want to make the distinction that at no point was an engineer making poor choices.

I want to point this out not to sound defensive, but rather to make it clear that when I use the term "tech debt" I am not saying it in a castigating or "accusational" way. There is no shame in tech debt.

(BTW, other engineers I've worked with, will add a "BOGUS" comment next to any line of code they are in fact embarrassed by with some explanation like "using very small number here, render crashes if border is zero thickness.". Do a search for "BOGUS" in the sources to discover you BOGUS debt.)

> I may be splitting hairs here but I want to make the distinction that at no point was an engineer making poor choices.

Financial debt can be both good and bad. Good financial debt lets you take advantage of opportunities now that you wouldn't otherwise be able to afford, and you end up better off in the end. Bad financial debt leaves you worse off in the end. Taking on financial debt absolutely can be a poor choice.

I don't see why these same qualities can't show up in technical debt as well. So sometimes engineers might be making poor choices, the point is to evaluate whether the debt is taken on to exploit an opportunity, evaluate whether you'll be better off for taking on that debt, and to ensure you pay it back in a timely manner.

I think you are taking it personally, tech debt usually isn't the fault of individual engineers. It is leadership who chooses to value initial short term speed over extensibility, maintainability, etc.

sometimes it is obvious to the engineer that this will cause problems in a few months, but the first deadline is in a few days, and that's all leadership cares about.

This is something that I see "daily" currently working as a contractor on web development. Frameworks like Bootstrap are used to quickly/cheaply deploy a site but by not doing things "properly" from the beginning it creates a debt to be paid later with compounds.

I dislike working with Bootstrap projects but I understand that "getting into debt" sometimes is unavoidable. And debt isn't necessarily a bad thing.

> I am someone else who apparently never understood what technical debt was supposed to mean.

I've always assumed engineers (myself included) write code to the best of their abilities to solve a given problem at the time.

Another way of looking at technical debt, that I unfortunately must use regularly, is debt accrued by not updating systems. I work with hardware and software that is, in some cases, from the 80's. As these machines age, they become more and more likely to break. The longer we wait to replace them, the more value their initial investment is worth, but also the greater the chance that production will be halted for months while we try to design and implement a new system. So this is technical debt accrual as a function of time, not as a function of development speed.

Writing code to the "best of your ability" is something I've seen create a lot of problems because after you get about 75% done you probably realize how to do it better, and that happens repeatedly. In extreme cases I've seen mid-project framework changes multiple times.

Writing code that isn't great but works in order to ship a product in a timely manner incurs technical debt because you may have to do more work in the future to fix it once it is in use. But ideally your project is generating real income on that technical debt so it's probably better to have something to works right now vs something that's going to be perfect when it's done, eventually.

> I've always assumed engineers (myself included) write code to the best of their abilities to solve a given problem at the time.

In your own personal project, I'd probably agree. But in my experience in a work project there can often be imposed deadlines or project changes that result in engineers writing code that they themselves know is suboptimal even at the time.

In other words, the sort of change that might include a comment like "I know this isn't the best way to do this but don't have time to do it the best way right now." It's not the best I can do overall, but it's the only thing I'm able to do for whatever reason. That's the kind of thing I'd call tech debt.

I've written code that I knew could be better when I wrote it. "Better" can mean a number of things. More readable, more efficient, more self contained, lower cyclomatic complexity (whatever TF that means).

I never intended to put shame on tech debt. It's usually a now vs later (or never) tradeoff.

"...everything we do that is 'technical' has ... consequences that go beyond the technical: The mere fact that most of the technical things we choose to do are done for non-technical reasons is enough to establish that."

Aha! But people do things just for technical reasons that don't affect the users in any way.

One could claim that just refactoring code without changing anything is a "purely technical" exercise.

What I've seen developers spend time on, that has absolutely no effect on end users in a large C++ codebase:

* Changing old C-style string handling to std::strings

* Change naming convention to uniform

* Random formatting that should be done automatically but someone decided to do by hand

* Sundry "modernizations" like replacing vanilla C++ loops with C++ range based for loops etc

To the extent that these changes actually improve the non-functional quality attributes of the system, those gains can be converted into business or customer utility.

Improved maintainability => lower innovation costs, and those savings can turn into profits and/or happier customers.

Improved security => reduced risk of exploit, and that improved posture can be turned into profits and/or happier customers.

I acknowledged that not all changes of the sort you list do yield actual improvement in the quality attributes.

> One could claim that just refactoring code without changing anything is a "purely technical" exercise.

The reason is still partly non technical; the goal is to make future changes less costly or less dangerous.

Does it matter that they are less costly or less dangerous for technical reasons? lol
The examples you give look more like inefficient resource (developer time) allocation - AKA Yak Shaving - rather than technical debt.

Nevertheless, people doing things for just technical reasons does sometimes create technical debt, as when doing so over-complicates the implementation to no observable end. So? If anything, these cases stand as counter-examples to the author's argument that technical debt is not technical.

> "Technical debt is the burden that implementation choices may place on future development"

True, provided we understand that those choices are not always conscious. I more commonly use the term looking back: some code technically works and at least minimally satisfies current use cases, but is hard to read and therefore hard to maintain or extend and bug-prone, so it needs to be refactored, improved, and/or modernized.

Before the term "technical debt" existed, it could be hard for developers to convince management of the need to clean up existing code. It sounded like just some thing that crazy programmers wanted to do - spend time and money for something that delivered nothing new. Now managers can understand the need to pay off "technical debt."

> looking back .. minimally satisfies .. is hard to read

Interesting. I wonder if there is an analogy to the first draft of a book. Everything needs "editing" -- that is a given. Some writing only needs line editing; some needs a restructuring, a rewrite, etc.

> "Technical debt is the burden that implementation choices may place on future development."

> With regard to its coherence, I say that it is empirically verified: it actually happens!

Something happens, on this we can agree, but if you are making checkers and find out you need chess, it isn't that making chess is any harder than it was before you did anything -- so no, I would not agree that it placed any burden on future development.

No, I think the real issue is that you have already paid for checkers and so you feel unhappy that your time (and maybe money) was wasted on checkers when you simply can't sell checkers because all along you needed chess.

> The mere fact that most of the technical things we choose to do are done for non-technical reasons is enough to establish that. The root cause of a problem and its broad consequences are separable concerns.

The root cause is that you do not know what you want. Writing the crappiest version of checkers as quickly as possible is a great way to find out it is the wrong thing. Trying to write an "abstract board game" instead of just writing checkers so that the decision to choose checkers or chess could be delayed as long as possible is not: It assumes that it is mere time that informs us of what we want, rather than the feedback of seeing what we don't want.

> it is completely reasonable to consider the situation where, say, I give a farmer cash in return for some produce at harvest time to be a debt

We can fantasize about a great many things, including this, but software is not produce that is harvested and sold; you do not plant great software seeds to grow into great software trees. No, the debt is the cash that the farmer received, just like the debt is the cash you receive to write the software. The software itself is not debt and never was.

not all "technical debt" is wanting chess when we built checkers.

it can just be building a minimal chess quickly using methods/frameworks that are not easily extensible to future requirements related to chess.

the vast majority of software projects will have features/requirements that evolve after the initial design, it is a rabbit hole to try and guess all of those, but some things are just common sense but would add a little time to the first milestone. then you are in the position of tacking on things indefinitely making it a horrible tangled mess.

> it can just be building a minimal chess quickly using methods/frameworks that are not easily extensible to future requirements related to chess.

You should not build something you do not need if you know it is wrong and you will not need it.

That is just wrong.

Many engineering managers do this to “show progress” but this is because they are bad at their job.

On the other hand, if you need it so the UI team has a mock to work against (so that they can explore what interfaces they really need), it isn’t debt at all.

Technical debt doesn't even need to be related to future requirements. It could be building something that's only mostly right to get something out faster.
Yup. For instance, he mentions interest rate. Why? How is it useful to think about it and precisely define it in this context? Next article: the cloud isn't even a cloud, it isn't made out of small particles of water!
The "interest" is a metaphorical measure of how sustainable your situation is, and how urgently you need to address the "principal".

If you incur technical debt as a mismatch between your codebase and your requirements (owing to the evolution of requirements) initially you may just be able to work around the mismatch, but it starts to incur "extra" work - this has been called the "interest" in the extended metaphor. Everything you do that isn't addressing the mismatch keeps adding to the debt though, so eventually the "interest" becomes equal to your entire budget and no more forward progress can be made, and typically bankruptcy is called (give up on code base, propose rewrite to address the actual requirements) and the cycle starts again.

Debt would be if someone said "I need to build a bridge across here that can handle an Army, and I've got $1m", we engineers reply "It will take $2m", and they respond "Ok, I will borrow $1m so you can build the bridge I need".

Instead what happens is they say "Well, build what you can for $1m", and you say "Ok, we can make 'a bridge' for that", and then either (a) your infantry can cross, but the tanks have to get diverted 20 miles out of the way, or (b) the tanks end up in the river along with the bridge. Since (b) is bad, you then have to spend a lot of time planning the routes for the tanks, and making sure the tanks have the right air cover, etc etc, i.e. doing more work. More likely, however, is that the manager, who is not a structural engineer, sees a perfectly good bridge and orders the tanks across anyway, causing the loss of the bridge, the tanks, and the war.

It's not debt. It's just (at best) an incomplete solution or (at worst) a bad solution that fails at the worst possible moment - e.g. database collapses during registration for the largest event of the year.

Ah, but surely, if you build the lightweight solution for $1m, and acknowledge the increased costs of managing the problems that it doesn't solve, then thats fine? Sure, but that's not technical debt either! That is scoping: we (engineers + business) identify a workable solution that provides some business value. And then we do that well. When Cunningham, for example, talks about what to do about debt, e.g. YAGNI, these are all good ideas: scoping. But the term "debt" is incorrect in this case. The term "debt" will only ever get a team in trouble as it indicates that the team is unwilling to confront the actual problem as engineering, but only as a broken metaphor.

> It's just (at best) an incomplete solution or (at worst) a bad solution that fails at the worst possible moment

Well, those are two possibilities, but a third is that you don't need it because of one of several possible reasons.

The debt metaphor still fails to hold up; the nice thing about accepting "technical debt" into your project is that you may never come upon a time where it needs to be paid off at all. Not all tech debt must be paid off.

Usually only the highest priority tech debt can actually be paid down, and it doesn't always come with an interest cost. But when it starts to "come due," if you're an engineer in the hot seat, you can often (usually) tell pretty quickly just how much the "interest payment" actually affects your ability to deliver future iterations.

Your "customers" or stakeholders can tell too, indirectly, when your estimates start outpacing their "very reasonable expectations."

"Technical debt is the burden that implementation choices may place on future development."

Any choice you make now, may place a burden in some possible future.

Some more than others.
Absolutely, but the article complains about lack of rigor and this definition doesn't provide it.
> Arguing over dictionary definitions is not going to lead to anything useful in this matter.

> If we are going to be pedantic

The whole article was about going to be pedantic over dictionary definitions.

"Now, one major concern in academia is rigor. Academics like to get deep into a topic, examine the nuances, and bring clarity."

I suppose it's hard to argue against that words in "technical debt" were chosen poorly: it's not debt and it's not technical.

Maybe better definition is needed.

I prefer to think of it as, the more there is the more there is to fail. I apply that to the entirety of the application not just the tiny part I write.
> It is completely reasonable to consider the situation where, say, I give a farmer cash in return for some produce at harvest time to be a debt.

Being entirely-too pedantic about financial instruments: that’s a commodities future. Financially, it’s not a liability, it’s an asset: you’re owed something. It’s not really a good comparison to technical debt, which is at the very least clearly a financial liability of some kind — something that makes your company worse-off for having it.

I think the author of the article, meanwhile, was interpreting “debt” to specifically be shorthand for “a loan taken out against future earnings.” Loans a company takes out give them both a short-term asset (cash flow) and a matching long-term liability (loan repayment.) Which seems kinda-sorta like what “technical debt” is motioning at: you get short-term gains (working code) but a long-term liability (the need to rewrite said code when its lack of robustness or unmaintainibility causes it to break down in the face of scaling challenges.)

But this analogy is still pretty far off-the-mark, because:

1. You need to pay back a loan, or bad things happen to your company; but you won’t necessarily need to pay back technical debt — sometimes, despite your company scaling as a whole, the relevant software component just never needs to scale, and so it that particular technical landmine just never “goes off”;

2. loan repayments are predictable, and involve entering into contracts where you either conscientiously repay the debt month after month with low premiums, or you fail to make payments and the loan comes due. Technical debt is nothing like this; there’s no counterparty forcing IT companies into a default situation of paying down their tech-debt little-by-little. (Wouldn’t that be great?)

Thus, a loan against future earnings is likewise a bad analogy for what technical debt “is.”

Dredging around in finance for a more exact analogy for technical debt, a very close one might be writing and selling call options against your own company, where your share price hasn’t yet reached the strike price for these options. You would be raising short-term capital, but creating a future liability — in that when your share price hits the strike price (i.e. when your company grows), people would then have a growing incentive, commensurate with the growth in your share price over the strike price, to exercise their purchased call options by buying at the agreed strike price; and then some of those people — an unpredictable subset of them — would turn around and dump the resulting shares on the market at market value, lowering your share price.

IMHO, the analogy is pretty okay because both scenarios are the same sort of “setting up a bomb for yourself that may go off at an unspecified time into the future, but only contingent on your company being successful, where you’ll have more resources to deal with it” problem.

But on the other hand, you can’t really defuse having sold call options, in the way that you can “pay down” tech debt. (I guess you could try to buy back the call options — but the holders are under no obligation to sell them back to you. Whereas tech debt has no such willful resistance to being fixed.)

So even this analogy, though better, isn’t a perfect one.

Truly, though, although we can’t say we know what technical debt is specifically, we can probably be pretty explicit by just generalizing the term: all of what we call “technical debt” is in fact some kind of financial liability (in future engineer-hours needing to be spent.) So perhaps “technical liability” is, although vague, the best we can do.

If it was a futures contract, the cash and the product would be exchanged at the expiry date. If the cash is provided today in exchange for a product in the future, that is indeed a debt - some kind of zero coupon bond where they payment is in cattle.

But I think you're reading too much into the terminology. The concepts being discussed here really don't have anything to do with finance.

> If it was a futures contract, the cash and the product would be exchanged at the expiry date. If the cash is provided today in exchange for a product in the future, that is indeed a debt - some kind of zero coupon bond where they payment is in cattle.

Futures contract, and then a loan taken out with the future in your possession as the collateral. Which is the thing any large low-margin operating company holding some futures would do by default (through the commercial paper market), because cashflow. (Or they’d just sell the future to the mutual fund they likely hold equity in. Same difference.)

> But I think you're reading too much into the terminology. The concepts being discussed here really don't have anything to do with finance.

The author of the article was also “reading too much into the terminology”, though. They were trying to pick apart the financial implications of technical debt as a type of loan — when it’s clearly not any type of loan. But the exercise they went through seemed fun, so I figured I’d try shoving the concept of tech-debt into some other pigeonholes, to see if it could actually fit one of them.

I encourage everyone with experience in both finance and tech to try this exercise; maybe there’s some exotic financial instrument that actually does exactly mirror the “mechanics” of keeping tech-debt around, such that examining the properties of that instrument could elucidate the previously-vague properties of technical debt (in the same way that the properties of mathematical objects can be elucidated by mapping them into different equivalent objects from other mathematical subfields.) Maybe we could even prove some things about technical debt. Wouldn’t that be neat?