As an engineer I see every piece of added complexity as a carrier of a little bit of liability. Yes that piece might add functionality, increase reliability an such, but it also needs to be maintained, understood, documented and increases the complexity of the whole (and thus makes it unlikelier to some random developer just understanding it).
Technical debt is when pieces of your code cannot simply be maintained and understood, or when these pieces produce constant maintenance issues because they have been assembled the wrong way or a dependency is no longer maintained itself.
A significant part of my refactoring, is removing code.
I always say that the best code I write, is the code I don’t write. It can take longer to simplify a block of code, than it took to originally write.
I also tend to use “light touch” documentation[0]. I use headerdoc-style function and property intros, with occasional terse inline comments for inscrutable parts. These inline comments always talk about why I’m doing something odd.
And I eat my own dog food. I maintain almost everything I write, so I write code and documentation that I want to see, six months down the road.
And testing. I do a lot of that; especially monkey testing[1].
Do this metaphors really help anyone? To me it only obfuscates the situation. It doesn't give me any clarity. Honestly "technical debt" doesn't mean much to me and I've seen the words mostly being used as a shielding mechanism by developers who want to avoid discussing difficult topics.
> Do this metaphors really help anyone? To me it only obfuscates the situation. It doesn't give me any clarity.
To be fair, leaving aside how fitting or unfitting it is, the metaphor is too kind to cause any reaction at all.
If you say "we can take a bit of technical debt to get more work done today, we can always pay it off later", people would nod and move on. The reaction you get would be, at most, on the same level as someone watching TV news about a tragedy on a different continent ("Oh no. Anyway...").
But if you say "we can cook today's meals without washing any pots/pans/spatulas/etc and save time and money that way, we can just keep doing it every day until the first roaches appear", even though the message probably gets across way more clearly, you'd get a warning to watch your language and keep it appropriate, and how dare you compare the company to such a nasty restaurant.
"Our technical debt is starting to become too much" doesn't ring the same as "there's too many roaches and they are actually starting to get in the way of our cooking".
Seems like a similar thought to "Programming as Theory Building"[1].
The paper is well worth reading, but the TL;DR if you don't wanna: the "theory" of a program (how does it fit together? What extensions/modifications would work well, how should it evolve to handle new cases, etc.) is contained only in the mind of the coder; documentation, spoken explanations, etc. are attempts at describing that theory, but they are necessarily a lossy encoding of it. Certainly attrishing everyone who knows something about a codebase would be extremely foolish under Naur's argument.
Debt, I guess to me, is code deviating from a known better theory for it to follow.
The "attrishing" in your comment made me go looking, and Wiktionary [0] says the verb form "attrit(e)" exists and is likely a quite old backformation that has fallen out of common use.
The older and more experienced I get, the more I lean towards not implementing anything more than the bare minimum.
I think juniors are more prone to building supposed "technical assets" in the hope it might get used. This could be microservices or a nosql db, or kubernetes operators, etc. Part of this is just a desire to try things and do some resume driven development (which I guess is fair). These things do inevitably end up being tech debt a good portion of the time, though the other portion are good innovations which unlock opportunities.
With experience comes an appreciation of what is really needed and a knowing of what is needless, and also the ability to create a solution closer to when it is needed (both because one is quicker at coding it, and because with a delay comes better data and thinking on the solution).
I think building a good theory and consensus among the team ahead of time might be a better use of time.
I agree 100%. If you want to deliver valuable software you need short iterations because you need to validate assumptions. Anything you build more than the bare minimum is not included this feedback loop so your assumptions are not getting validated and you don't know if you're building the right stuff.
This is not easy though. You don't want to paint yourself into a corner because of earlier design decisions that turned out to be unexpectedly very costly. So you need to have some set of assumptions that you will not get a chance to validate soon. I guess experience helps here.
There is indeed this important aspect, but with this mindset we would never have implemented compilers, databases with their own query language, etc...
I never lost a bet I made in """overengineering""" a solution to a problem and was always proven right in a matter of months. This is especially easy when the proposed solution brings structural improvements to the time it takes to implement a certain class of features. It's just a matter of comparing the time it takes to implement that "sophisticated" solution vs the speedup to implement such a feature using said solution times how many potential features there are in this class times the probability the company will need it at some point. And yes, in my case this implied writing "mini-compilers" or "mini-debuggers".
Some people see technical debt as a list of missing features, but it should be a list of the problems that you know you have to vs want to solve. The list can vary but should include known bugs and errors in your code. It should also include how readable your code is and any bloat you might carry. Slowness in build and execution time needs consideration as well.
>The systems programmer has read the kernel source, to better understand the deep ways of the universe, and the systems programmer has seen the comment in the scheduler that says “DOES THIS WORK LOL,” and the systems programmer has wept instead of LOLed
You can't just be in your codebase and start doin' technical debt like that.
1a. Technical debt is when you...
1b. Okay, wait. Technical debt is when you write code but, like, the kind of code that you know Future You is gonna hate.
1c. Let me try this again.
1c-a. It's when you're coding and you think, "I'll fix this later," but then later turns into never. And now there’s spaghetti code in a project that was supposed to be a sleek pipeline.
1c-b. Like, imagine you're about to refactor something, but you go, "You know what? The deadline's tight, so I’m just gonna... not." That’s technical debt.
1c-b(1). If you're writing code and you think, "Wow, I hope no one sees this commit message," congratulations, you’ve accrued technical debt.
1c-b(2). It’s like leaving a TODO comment, except the TODO becomes, “Oops, it’s been in production for three years.”
1c-b(2)-a. You can write a clever workaround here, but the workaround has to work around the workaround of the workaround from three sprints ago.
1c-b(2)-b. Also, don't forget to include an inline comment that says, "This should be fine for now," which is developer code for “This is the next intern’s problem.”
1c-b(2)-b(i). Fun fact: the "for now" phase lasts forever, and the fix will never be fine.
1c-b(3). Seriously though. Technical debt is when your code does the thing but not in the way anyone would ever want it to. And if your app suddenly catches fire during peak traffic, that’s just the interest being collected.
a lot of tech debt is used to palliate the effects of weak leadership in lame organizations, but say, doing a feature demo with hardcoded or simulated data that closes a sale is smart leverage.
ultimately the purpose of any feature is to discover market demand for fit. the faster you can do that, the better your product will be. when we lose sight of that signal-discovery purpose and think we're building a precision machine part or a bridge as some kind of public service, I think we lose the plot.
people should learn to love tech debt, it's high value, and when it becomes a problem, fixing it is also high value.
A debt vs an asset is a matter of context and perspective more than an essential property.
Data may be an asset for you. But the very same data may because a debt (because it becomes hard to keep relevant or accurate) or even a burden (because it exposes you to unwanted disclosures and potential commercial and legal consequences).
Remember having a very hard time explaining to three (of course non-technical) cofounders of a… peculiar online payment platform that hoarding all payment and behavior stats of users was maybe not the rich and lucrative endeavor they were looking for if they did not put the required effort in the design and multi-level security of the storage. What was bound to happen, happened.
I can't believe people are still talking about tech debt like it's a real thing.
Debt is the amount owed on a loan. There is no loan taken out, nor terms. There is no creditor. There is no term sheet. There is no capital. There is no security. There is no debt. It's imaginary. Not imaginary like how money is imaginary. It literally does not exist, in any way shape or form, other than as myth, parable, metaphor, or ghost story. Better not incur tech debt, the boogie man will get ya! (Or, as is much more popular as a rationalization: that debt as fiscal policy is actually a good thing, so 'tech debt' must similarly be good)
If it was real debt, the bank would have called in their loans on the deadbeats and forced them to fix their shit, far more often than actually happens. But it's not debt. It's just lazy people putting off what they don't feel like doing.
The idea behind tech debt is just the state of cheating yourself by doing a shitty thing for short-term gain. It has nothing to do with money. It's an intellectual rationalization for being lazy. ("Hey, it's no big deal that I didn't add security to the web service, it's just tech debt! I'll pay it back later!")
It's like drinking too much booze, eating too much pizza, and not working out, because it's easier to do that now, with the promise of working out later to relieve the "debt". But you never stop pigging out, and you never start working out. It's just cheating yourself in the future to be lazy today with no material consequence.
Technical debt is all those decisions you make that are not the optimal way of doing things. Eventually I seen entire companies screech into a halt because the code couldn't be reasoned about, things were too fragile so any change caused something else to break, and/or performance was so bad that tjry were bleeding money.
It's all debt. It's time debt. You gotta pay with time for every thing you gotta build, tech debt adds in more time you always gotta pay every time you do things.
OK, if drinking too much booze, eating too much pizza, and not working out are instrumental in rapidly getting the service in the hands of paying users, then it's like those things.
It's called "tech debt" rather than "tech indulgence" because it is helpful but has to be repaid in time.
You don't repay tech debt because it's not an actual debt. It's just taking shortcuts. You don't have to repay anyone for taking a shortcut. You do have to repay a debt, or your fucking car gets repossessed. And it's not like debt in any other way either. Hence tech debt is not debt.
A better metaphor: it's like adultering extra-virgin olive oil with cheap refined oil and calling that "oil debt". It's not debt, you're just cheating. Sure, you're "delivering a product into the hands of users faster". There is nobody to pay back, there is nothing you owe, unless you get caught. Similarly, 'tech debt' never needs to be paid back, unless one day it bites you in the ass and you can't get around it and have to do it the right way. Actual debt does not work like that at all.
Or, actually accurate: building a physical metal machine with poor tolerance and quality control. Building it to high tolerances and quality would have taken more time or expense, so they instead built it shittily so they could deliver it quicker. And it may work for the customer for a little while, but it will also have defects and stop working, and then the customer is screwed. This is not "machine debt". It's just a shitty machine, made by lazy people, so they could make money quicker.
That is not how debt works. It's not debt. It's just a bad metaphor for being lazy and taking shortcuts. And it's being used now to justify being lazy and taking shortcuts. It's crazy that so many people just eat these rationalizations and then continue them as if they make sense. The dumb leading the dumb.
(Also, what the hell? how could drinking and eating too much lead to people getting a product??)
I totally agree. Technical debt is a vague metaphor that is not very helpful. It doesn't accelerate discussions. It doesn't help us make better or quicker decisions. In fact the opposite is true, someone will say something about tech debt, everyone will agree (but everyone has their own interpretation so everyone actually thinks something different) and the topic is shoved under the carpet until it becomes relevant again.
I don't like metaphors in general, but this one tops the list.
The problem with this metaphor is that it's the first time I see the term "technical asset". And this is likely due to the fact that it was coined to explain to non-technical people with decisional power why development was getting so slow in certain situations using language they were used to.
But technical assets, or should I say, technical investment is just as important. A 10x developer isn't someone who codes 10 times faster. It's someone who code 10 times less.
Technical debt is when pieces of your code cannot simply be maintained and understood, or when these pieces produce constant maintenance issues because they have been assembled the wrong way or a dependency is no longer maintained itself.
Good code is code that people want to maintain.
I always say that the best code I write, is the code I don’t write. It can take longer to simplify a block of code, than it took to originally write.
I also tend to use “light touch” documentation[0]. I use headerdoc-style function and property intros, with occasional terse inline comments for inscrutable parts. These inline comments always talk about why I’m doing something odd.
And I eat my own dog food. I maintain almost everything I write, so I write code and documentation that I want to see, six months down the road.
And testing. I do a lot of that; especially monkey testing[1].
[0] https://littlegreenviper.com/miscellany/leaving-a-legacy/
[1] https://littlegreenviper.com/various/testing-harness-vs-unit...
To be fair, leaving aside how fitting or unfitting it is, the metaphor is too kind to cause any reaction at all.
If you say "we can take a bit of technical debt to get more work done today, we can always pay it off later", people would nod and move on. The reaction you get would be, at most, on the same level as someone watching TV news about a tragedy on a different continent ("Oh no. Anyway...").
But if you say "we can cook today's meals without washing any pots/pans/spatulas/etc and save time and money that way, we can just keep doing it every day until the first roaches appear", even though the message probably gets across way more clearly, you'd get a warning to watch your language and keep it appropriate, and how dare you compare the company to such a nasty restaurant.
"Our technical debt is starting to become too much" doesn't ring the same as "there's too many roaches and they are actually starting to get in the way of our cooking".
The paper is well worth reading, but the TL;DR if you don't wanna: the "theory" of a program (how does it fit together? What extensions/modifications would work well, how should it evolve to handle new cases, etc.) is contained only in the mind of the coder; documentation, spoken explanations, etc. are attempts at describing that theory, but they are necessarily a lossy encoding of it. Certainly attrishing everyone who knows something about a codebase would be extremely foolish under Naur's argument.
Debt, I guess to me, is code deviating from a known better theory for it to follow.
[1]: https://pages.cs.wisc.edu/~remzi/Naur.pdf
[0] https://en.m.wiktionary.org/wiki/attrit
I think juniors are more prone to building supposed "technical assets" in the hope it might get used. This could be microservices or a nosql db, or kubernetes operators, etc. Part of this is just a desire to try things and do some resume driven development (which I guess is fair). These things do inevitably end up being tech debt a good portion of the time, though the other portion are good innovations which unlock opportunities.
With experience comes an appreciation of what is really needed and a knowing of what is needless, and also the ability to create a solution closer to when it is needed (both because one is quicker at coding it, and because with a delay comes better data and thinking on the solution).
I think building a good theory and consensus among the team ahead of time might be a better use of time.
This is not easy though. You don't want to paint yourself into a corner because of earlier design decisions that turned out to be unexpectedly very costly. So you need to have some set of assumptions that you will not get a chance to validate soon. I guess experience helps here.
I never lost a bet I made in """overengineering""" a solution to a problem and was always proven right in a matter of months. This is especially easy when the proposed solution brings structural improvements to the time it takes to implement a certain class of features. It's just a matter of comparing the time it takes to implement that "sophisticated" solution vs the speedup to implement such a feature using said solution times how many potential features there are in this class times the probability the company will need it at some point. And yes, in my case this implied writing "mini-compilers" or "mini-debuggers".
>The systems programmer has read the kernel source, to better understand the deep ways of the universe, and the systems programmer has seen the comment in the scheduler that says “DOES THIS WORK LOL,” and the systems programmer has wept instead of LOLed
1c-a. It's when you're coding and you think, "I'll fix this later," but then later turns into never. And now there’s spaghetti code in a project that was supposed to be a sleek pipeline.
1c-b. Like, imagine you're about to refactor something, but you go, "You know what? The deadline's tight, so I’m just gonna... not." That’s technical debt.
1c-b(1). If you're writing code and you think, "Wow, I hope no one sees this commit message," congratulations, you’ve accrued technical debt.
1c-b(2). It’s like leaving a TODO comment, except the TODO becomes, “Oops, it’s been in production for three years.”
1c-b(2)-a. You can write a clever workaround here, but the workaround has to work around the workaround of the workaround from three sprints ago.
1c-b(2)-b. Also, don't forget to include an inline comment that says, "This should be fine for now," which is developer code for “This is the next intern’s problem.”
1c-b(2)-b(i). Fun fact: the "for now" phase lasts forever, and the fix will never be fine.
1c-b(3). Seriously though. Technical debt is when your code does the thing but not in the way anyone would ever want it to. And if your app suddenly catches fire during peak traffic, that’s just the interest being collected.
Sometimes your product people aren't good. Sometimes the features aren't worth a damn.
ultimately the purpose of any feature is to discover market demand for fit. the faster you can do that, the better your product will be. when we lose sight of that signal-discovery purpose and think we're building a precision machine part or a bridge as some kind of public service, I think we lose the plot.
people should learn to love tech debt, it's high value, and when it becomes a problem, fixing it is also high value.
Data may be an asset for you. But the very same data may because a debt (because it becomes hard to keep relevant or accurate) or even a burden (because it exposes you to unwanted disclosures and potential commercial and legal consequences).
Remember having a very hard time explaining to three (of course non-technical) cofounders of a… peculiar online payment platform that hoarding all payment and behavior stats of users was maybe not the rich and lucrative endeavor they were looking for if they did not put the required effort in the design and multi-level security of the storage. What was bound to happen, happened.
Debt is the amount owed on a loan. There is no loan taken out, nor terms. There is no creditor. There is no term sheet. There is no capital. There is no security. There is no debt. It's imaginary. Not imaginary like how money is imaginary. It literally does not exist, in any way shape or form, other than as myth, parable, metaphor, or ghost story. Better not incur tech debt, the boogie man will get ya! (Or, as is much more popular as a rationalization: that debt as fiscal policy is actually a good thing, so 'tech debt' must similarly be good)
If it was real debt, the bank would have called in their loans on the deadbeats and forced them to fix their shit, far more often than actually happens. But it's not debt. It's just lazy people putting off what they don't feel like doing.
The idea behind tech debt is just the state of cheating yourself by doing a shitty thing for short-term gain. It has nothing to do with money. It's an intellectual rationalization for being lazy. ("Hey, it's no big deal that I didn't add security to the web service, it's just tech debt! I'll pay it back later!")
It's like drinking too much booze, eating too much pizza, and not working out, because it's easier to do that now, with the promise of working out later to relieve the "debt". But you never stop pigging out, and you never start working out. It's just cheating yourself in the future to be lazy today with no material consequence.
It's all debt. It's time debt. You gotta pay with time for every thing you gotta build, tech debt adds in more time you always gotta pay every time you do things.
It's called "tech debt" rather than "tech indulgence" because it is helpful but has to be repaid in time.
A better metaphor: it's like adultering extra-virgin olive oil with cheap refined oil and calling that "oil debt". It's not debt, you're just cheating. Sure, you're "delivering a product into the hands of users faster". There is nobody to pay back, there is nothing you owe, unless you get caught. Similarly, 'tech debt' never needs to be paid back, unless one day it bites you in the ass and you can't get around it and have to do it the right way. Actual debt does not work like that at all.
Or, actually accurate: building a physical metal machine with poor tolerance and quality control. Building it to high tolerances and quality would have taken more time or expense, so they instead built it shittily so they could deliver it quicker. And it may work for the customer for a little while, but it will also have defects and stop working, and then the customer is screwed. This is not "machine debt". It's just a shitty machine, made by lazy people, so they could make money quicker.
That is not how debt works. It's not debt. It's just a bad metaphor for being lazy and taking shortcuts. And it's being used now to justify being lazy and taking shortcuts. It's crazy that so many people just eat these rationalizations and then continue them as if they make sense. The dumb leading the dumb.
(Also, what the hell? how could drinking and eating too much lead to people getting a product??)
I don't like metaphors in general, but this one tops the list.
Yes, it started as metaphor which caught on enough to be used as the name for a phenomenon/choice that does exist beyond myth.
But technical assets, or should I say, technical investment is just as important. A 10x developer isn't someone who codes 10 times faster. It's someone who code 10 times less.