The True Meaning of Technical Debt (2020)
refactoring.fm
refactoring.fm
https://www.youtube.com/watch?v=XakfJ2spb3w
tl;dw: Technical debt is equivalent to the interest you are paying on it, where interest == pain. Some debt is planned and low interest, like a mortgage. Other debt is unplanned and high interest, like a credit card or payday loan. Sometimes that interest allows you to get larger returns. For example, if you could take out a loan at 3% in order to invest at 8% over the life of the loan, that's a pretty good deal, as long as you can pay it down. but, if you let that interest get out of control, if you don't pay down the principal, then it becomes more painful.
https://web.archive.org/web/20161223143702/http://higherorde... https://news.ycombinator.com/item?id=8777237
From the post:
> Call options are a better model than debt for cruddy code (without tests) because they capture the unpredictability of what we do. If I slap in an a feature without cleaning up then I get the benefit immediately, I collect the premium. If I never see that code again, then I’m ahead and, in retrospect, it would have been foolish to have spent time cleaning it up.
> On the other hand, if a radical new feature comes in that I have to do, all those quick fixes suddenly become very expensive to work with. Examples I’ve seen are a big new client that requires a port to a different platform, or a new regulatory requirement that needs a new report. I get equivalent problems if there’s a failure I have to interpret and fix just before a deadline, or the team members turn over completely and no-one remembers the tacit knowledge that helps the code make sense. The market has moved away from where I thought it was going to be and my option has been called.
Originally I wanted to write that there are two different things that get called "technical debt". In one case, the choice is between "clean code now" and "quick and dirty code now, sell version 1.0 to pay the bills, refactor the code, publish version 1.1". In the other case, the choice is between "clean code for more money" and "quick and dirty code for less money" with no itention to fix it later.
Technically, only the first case should be called "debt". But sometimes managers pretend it's the first case, when actually it is the second case, to help developers save some face. So the developers keep adding "refactor XY, priority: low" to the backlog, and then at some moment the developers are moved to a new project, and the backlog gets silently deleted.
Then again, sometimes a big change is needed unexpectedly, and all those issues that were originally planned to silently die in the backlog suddenly need to be addressed. So, in this case, the "technical debt" was actually a bet that this situation is unlikely to happen. (Or maybe that it will happen in a sufficiently far future so that it will be another manager's problem.)
When applied to tech debt, it can be thought of as betting that product velocity will slow down, and you will have time to refactor/reliminate tech debt sometime later.
Of course when developing new product/startup product velocity only increases over time. And if you did accumulate tech debt - there will be some time when you will have to rewrite stuff from scratch, because refactoring and/or maintaining codebase will become unfeasible.
and it leads to conclusion that the best time to take on technical debt - is maintaining stable product, when product velocity is slow. you implement change quickly, then over time you refactor it. Which actually perfectly aligns with some agile methodologies (XP).
Can you keep shipping products if you never tidy up? Yes it’s possible but eventually it catches up to you.
There’s no specific point in time at which tidying up a warehouse is going to make or break a business but the untidy ones are more likely to be hard to hire for and more likely to catch fire.
And they’ll definitely slow down ability to ship products.
Warehouses that stay tidy have a predictable rate of shipping and reduced risks of accidents and fires.
Do you need to put that one single item in the right place every time to continue to ship anything? Well the answer is always no, but permanent short term thinking like that without ever tidying will always eventually cost you in the end.
Much easier to keep on top of it. Workers and new hires are also more effective.
I find that this metaphor doesn’t feel forced or stretched and it’s pretty intuitive and nicely harmonises with products and shipping terms that people use for software anyway.
I hold the opposite belief. Management speak is meant to obfuscate. Instead of just telling a report who disagrees with your decision based on expected outcome to think the way you tell them to, just say "think outside of the box". When you commit to "circling back", you're committing to nothing but having this idea cross the manager's mind at some point in the future.
It's weird that this is the conclusion the author came to from their linked article, considering this is in it:
> This is why you might be tempted to use the readily accessible management metaphor laced language which you’re familiar with. Don’t.
"Technical Debt" is this level of crummy metaphor. I love Cunningham's original definition. Do your best to model the business problem with the understanding you have. Later, pay down that debt by refactoring.
That's not what it means anymore. Tech debt means whatever the speaker wants it to mean. It's a get out of jail free card for any bad software choice.
"That choice will severely limit our capabilities in the future, and be incredibly hard to change."
"I'm willing to take on some tech debt to prioritize shipping."
See? No need to think.
For bonus points, mix the two up, so that not only is someone trying to sound managerial but failing by using the terms completely incorrectly, but then also rigidly enforce their incorrect understandings.
For instance, if you have lots of meetings and those meetings almost never produce "action items", and/or those action items never get done, you really do have a problem. If you don't like calling them action items, fine, find another word, but it'll be the same thing. But if you get a manager that insists that meetings always produce action items, no matter what, you get another sort of failure. It is a perfectly valid use of a meeting to get two groups together and just make sure they are on the same page about something. If that's all you ever meet about, there may be a deeper problem you should dig into, this shouldn't be your dominant form of meeting (unless you're in a position where that's your direct job), but it does sometimes need to happen.
I find it useful to dig down to the "original" meaning of a lot of these terms, think about what they mean and how to use them in my own head to put terminology on things, but not to be rigid about it.
I also observe that there are some managers who use the terms essentially correctly, and some that clearly fit into at least one of the two categories I listed at the beginning. They should be treated differently.
Defending a choice means actually defending it.
"If we don't ship this by X date, there won't even be a company to have the problem you're talking about."
"This choice will have less impact than you think for X reasons."
The problem is the specific reasons are often more in the family of "Shipping this is one of my KPIs and I'll be on some other team when the problems you're talking about are realized."
It's not just business vs. engineering anyway. Slow to ship? It's cause of all the tech debt. No tests? It's okay, just tech debt. No docs? Poor abstractions? Lack of understanding about the problem? Low skill with the technology at hand? It's all fine! Tech debt can be your scapegoat or hall pass for anything.
Missing/outdated docs/tests? Tech debt.
"Low skill with technology" - probably not as easy to lump it as 'tech debt', imo.
"Lack of understanding about the problem" - again, doesn't seem like tech debt, but... business debt. Tribal knowledge debt. Operational debt, but not explicitly 'tech' debt.
But... perhaps that's your point? It's easier to just say 'tech debt' for everything, even if it's plainly the result of underinvestment on non-tech things?
I on the other hand hate Cunningham's original definition because the metaphor maps badly, debt is not something that is poorly understand that becomes clearer the more information you have. Maybe that would be Technical Risk.
Your second example:
>"That choice will severely limit our capabilities in the future, and be incredibly hard to change."
>"I'm willing to take on some tech debt to prioritize shipping."
is a better metaphor because debt is the thing you take on that you need to pay off later with some knowledge of what level of debt you have. That said it's still sort of bad because debt would be nice to have sort of a ball park estimate of how much must be paid to get rid of it. If you don't have that estimate to go on it's beyond technical debt, and maybe more like technical favor owed to the mob.
Then there is accidental technical debt that is mostly due to lack of design skill / judgement that results in code smells, spaghetti code, poor abstractions and a codebase that sucks the life out of everyone.
When most people write about technical debt, they refer to the former while it is the latter that is much more costly and prevalent and yet, avoidable.
https://www.idginsiderpro.com/article/3488819/is-that-you-or...
Because code is written by humans, it behaves in ways that are not too much of a stretch to call “organic”.
We need more literal and figurative gardeners in programming, but everyone is a hurry to get their 10k hours in before they learn how to adult properly.
Gardeners make suggestions to plants, but the plants end up doing their own thing about half the time, so everything becomes a negotiation. When you try to assert your will too hard, you can kill the plant.
If you’re pruning a tree, the tree reacts by putting out more branches. If you do it too aggressively, the result is an ugly, unhealthy tree. If you stay below a threshold, everything keeps working as expected. So you have a pruning budget every year, and renovating a tree nobody has maintained may become a four or five year project.
The first year you cut off the sickly branches, and the one you keep walking into. Second and third year you do preventative maintenance, removing crossed branches and bark inclusions (future calamities). By year three you might begin making aesthetic decisions, and by year five you either finish up or start over because the tree has changed so much in the last four years.
Like software, usually this plan is in your head, not on paper. But for software it doesn’t have to be this way, we just haven’t done anything about it yet. I hope that 15 years from now we have ways to record code reviews not attached to PRs, noting targets of opportunity and storing them with the code. That way, when I’m adding a feature I can also look at the refactorings suggested by others, especially the ones that are not locally apparent, like architecture and code duplication issues. Having to fix a problem the moment you see it is a very ADHD mode of thinking.
But if something is done with plain bad code, it shouldn't be called tech debt. Something that outgrew its objective shouldn't be called tech debt. If something is a bug it shouldn't be called tech debt.
I agree with the rest of your comment, but something that outgrew its objective is almost text book tech debt. Instead of taking the time to build something new, or refactoring, you tacked it on to something existing.
If you build something properly (ie you did not deliberately made a choice of taking a shortcut), and it ages badly I called it Tech rot.
This is in contrast to the debt you have to pay each day in production.
We have a fair bit of that "extra mass", due to shortcuts taken many moons ago under tight deadlines. On a daily basis the code works fine, and does what the customer needs.
However due to it we spend extra time when we need to extend it or change it.
I don't think anyone refers to bugs as technical debt per-se. What I have seen is bugs that result from technical debt, and hasty bug fixes that create more technical debt.
Even thinking in terms of "investment" is gap thinking and treats human systems without human traits.
In a system of joint activity, people and artefacts work together in harmony. If they're not working together, it's not joint activity and if its not joint activity, that doesn't mean its debt either. It's dysfunctional.
Development, maintenance and operations are three fundamentally different and often opposing forces that no management is ever going to tackle right.
As a result you’ll have developers who build programs and then move on to build other things. You’ll have operations that’ll have enough know how to operate and error-handle but not enough to re-develop when the real world changes. By then, the developers have either moved on, are too busy or have forgotten enough of the project that no one is actually available to change the system to match the new reality. If by some happenstance, you actually do have someone who can redesign and reimplement the system, they will be given too little time to do a proper job, because developer resources are expensive. When the real world has changed enough times, you’ll have technical depth.
The only projects that can avoid it, are those big enough, to have their development team never leave and management willing enough to let the developers spend 1/5 of their time on maintaining the system.
That’s not to say that you should do nothing. Often it’s proven itself valuable, for us at least, to design systems with the full intention of throwing them away 5-10 years down the line. By not applying any sort of best-practices that are meant to make the systems easier to readjust during their life times, building them takes maybe 40% of the time, and if they are simple enough, you’ll never have an issue with them. Then 5-10 years later. You build their replacement. Which by theoretical means, would be a terrible business case after 15-30 years, but ask yourself how many smaller systems your enterprise organisation has, that are 15 years old. Out of the 300+ (and I say + because we don’t have the full picture) systems we operate, less than ten of them are that old, and every one of those systems is large enough to have full time developers working on them, often with a 9/10 focus on maintaining them, and only 1/10 on building stuff like more modern APIs for them.
... works only in an ideal world where nothing changes, i.e. where software written once is so good that you don't need to touch it.
In reality though, what happens to successful software projects is that once the management and the customers see that it works and is good enough they always, always start to request more features. In fact in the minds of managers adding a feature is just adding a feature, should be easy right? Well no, a lot of the times it's not. Too often adding features affects some core abstractions in the code in such ways known only to the developers that adds technical debt.
"Let's redesign the home feed. Should be easy, right?"
You can't get off the treadmill of updating and paying attention, because if you take your eye off the ball for just a few months, you wake up with outages because some service you depended on has deprecated their API and no longer support the way you were calling it before.
It's not even that they'll request things in the future. There's often a backlog of stuff that will be coming up. I've still had to fight on people pushing back with "quit 'overengineering'! YAGNI! etc" comments.
"Yes, we ARE going to need it. You agreed to it 3 weeks ago in meeting X! Just because it's not in this week's workload doesn't mean it will never happen. We're slated to have to do XYZ in 5 weeks - we understand enough of the problems that will face to be laying some of the groundwork (some extra refactoring/cleanup today in prep for work that will come down the pipeline 5-6 weeks from now)."
But... that will impact the schedule for today so... ignore it.
It's not always so blatant, and current projects don't suffer from this approach nearly as much as some past ones, but it happens.
Is the battle cry of losers
Who say “don’t bring that gun to the knife fight”
And ignore their opponents’ bazookas.
To keep running with the analogy, the sloppy developers will just take a credit card and max it out. The over-engineers will do credit default swaps on mortgage backed securities and tie up the whole economy.
I'd also add two subsets of the over-engineers. One subset are those that create frameworks to solve problems vs. address the problem directly. The other are those that introduce (language / datastore / build tool / etc.)-of-the-week to a codebase in an ad-hoc manner. And I'll admit, I've been both of those once upon a time...
Isn't the idea to make a non-over-abstracting engineer the principal, and then they will bring everyone else into line with code review, etc.
Wrong values propel them to the top.
The goal being, by including a point estimation AND volatility score, we are able to create much better signals for unknown unknowns.
A ticket pointed at a 3 with a volatility of 5 (volatility being 1-5) indicates that this should be an easy ticket but might require a much deeper amount of work for unknown unknowns.
I got this idea after learning about options where price is partly a factor of a security's volatility and thought it would also be an interesting way of modeling tickets.
Right now I have running on servers that I manage several old websites. One is a static site but it has content that has become broken over time. Flash animations and videos being the primary culprit. Another is a Drupal site running on an unsupported Linux release. These were developed many years ago, and met all their goals at the time. The people who developed them moved on. There were no requirements changes, no functionality that needed to be added or refined, the sites just simply needed to run as-is. But they were built on shifting sands. Operating systems are patched and updated and eventually EOLed. Frameworks like Drupal get patched and updated, and later versions are not backwards compatible but the prior versions are eventually not maintained, so there is significant work imposed upon site owners just to keep them running and safe. The same is true of any application framework/stack. Nobody wants to do the work to keep these sites updated, there is always a higher priority, but nobody wants them shut down either. So they stagnate, accumulating problem after problem just by existing, until they eventually collapse due to a critical failure that can no longer be repaired. Just like the house that eventually collapses due to deferred maintenance, the only solution at that point is an expensive rebuild.
Ironically the only computing environment I can think of that has largely sidestepped this is the mainframe. Yes the stodgy old corporate tech from the 70s that no self-respecting modern tech worker wants to touch is probably the only place you will find code written by your grandfather still running unchanged in production.
I imagine home loans would look a little different if there was a small percent chance on any given day that the bank would show up and ask you to pony up.
But in general, debt can be good given the right agreements in place.
I understand taking a loan from a business perspective, e.g buy more tractors for my farm to increase productivity. But how is using debt to buy a house increasing productivity?
But in a more abstract sense it's not all about money - it's about getting around roadblocks, for a cost. For example, being productive can include things like getting stuff done that you've been neglecting. Maybe a person bought a house to have space to practice yoga at home or something like that. They're knocking out things they've wanted to do but couldn't before. Also maybe increasing the demand of housing in your community by buying a house makes the local construction industry more productive.
A slipped knot. https://en.wikipedia.org/wiki/Bight_(knot)#Slipped_knot https://www.101knots.com/slipped-constrictor-knot.html https://www.101knots.com/mooring-hitch.html
You could say we need to create "slipped code".
We want houses before we can save enough money to afford them. We want applications before we know how many users will be slamming our servers. The common denominator here is time. We're trading in time - the only question to ask is whether it's being done for the right reason.
The wrong reasoning is usually something like "it would take too long to understand how to do it better".
When a better solution is understood to have obvious merit but nebulous short term applicability - that's probably good technical debt to take on.
Too often when I see this claim it’s used to defend the opposite idea - that we should assume that the future will continue to look like today.
A good engineer should be thinking about robustness and flexibility from day one. Many choices we make early on close off options in the future or make them achievable only at great cost and at the expense of other business goals.
By this I do not mean “future proofing” or trying to account for all possibilities or to solve for specific scenarios that do not yet exist - those too are traits of an inexperienced engineer.
To clarify my position I wrote this article below. One aspect is the fact that circumstances and thus requirements may change. This is not a misunderstanding or tech debt. This is just what it is, no need for any metaphors.
https://louwrentius.com/most-technical-debt-is-just-bullshit...
Unless you focus the discussion (e.g. on test coverage), which includes tossing out things that could arguably be "tech debt", most discussions break down.
Also, what if the business cost for slow development causes a negative impact? Sure the code and you resume look good, but your startup just became vaporware and ran out of money.
I wasted time before cleaning up code only for it to be dropped or for the code not needing any additional updates for over 5 years.
You can't always anticipate tech debt in advance so it often better to leave the quick and dirty solution and revisit if it becomes painful to update in the future.
It can become debt (or a liability in a more general sense) when you realize, a year or two later, that it's what you need but it's no longer compatible with the base system. So now it has to be cleaned up to be reintegrated properly, is it worth the trouble of the fix or should it be scrapped and restarted?
Or, worse, if it is in the system but disabled by something like a feature flag, it helps to ossify the underlying system because you now have something which depends on capabilities you want to change, but can't because it's in the system.
In a statically typed language this means care is taken with your core system to protect a feature that's not in use, but prevents compilation if you change its dependencies. And then you have to determine if the dependency change should be kept or not, if the unused feature should be kept or not, and if kept how to update it to use the changed dependency.
In many dynamically typed and interpreted language this means your core system is not stuck, but when you finally flip that feature flag on you'll realize you pulled the rug out from under yourself. Unless your tests are sufficiently comprehensive to trigger the error after a breaking change in the dependencies.
Yes, code that is not being used should be deleted as soon as possible. Even if it was the cleanest code ever written - delete it.
It is adding massive mental overhead for future work, especially as a new developer on the project - how do I know its not being used?
Engineering in general usually involves a trade-off. If you want a really fast car, it cannot have air conditioning. But also, if you want the car built in 12 hours, the engine might overheat every now and then. The point is, you can have technical debt and have understanding between business and engineering.
Tech Debt is a rational tradeoff, but when all decision makers are incentivized to only care about the short term, then it quickly becomes an unassailable barrier to future growth.
In theory you are right, tech debt is a tradeoff.
In practice what is happening is that people decide not to pay attention to design at all and just throw away every single "best practice" with the excuse that there is a short deadline.
Many cases, this short deadline is entirely illusory, especially in large corporations. Many times I just ignored the deadline on my own judgement and everything came out fine and everybody was happy.
Most of the time, in a crunch, you can still follow most of the good practice and identify only small number of things that are just too time-consuming to handle now. You can then plan so that it is easier to fix later.
For example: when in crunch, I tend to focus on overall design and APIs and try to concentrate the tech debt in implementation. It is usually much easier to fix individual modules when they have good APIs and interactions with other systems. Fixing bad design/architecture spanning multiple systems is much bigger issue and usually requires touching implementation anyway.
But that's not what usually happens -- I haven't noticed people actually planning technical debt.
Another issue with technical debt is that there isn't anybody to chase you to pay it off. At least with an actual loan there is a bank that chases you. This aspect is underappreciated -- I personally think it should cause us to err on the side of less tech debt.
Design-by-HR has led to so many awful, awful projects, endless grind, and disastrous architecture.
Technical organizations which dissuade the HR power grab, usually have a lot better technical management and therefore architecture - and the technical debt is minimized. Technical organizations which defer to HR-derived architecture decisions are doomed to become a churning quagmire.
HR people: you've got to learn to stop interfering with technicians and engineers, because of your career choice. You're really not needed by organizations that build their technical resources properly.
I know its not a popular opinion, but 30+ years of experience in the software industry, from top to bottom, including stints in HR projects, has led me to conclude: HR is never senior to technical staff. Ever.
HR is not your friend. It is an organizational adversary imposed, usually, by executives who cannot make technical arguments or see things through to completion, no matter the depth of their understanding of the subject in focus, or otherwise.
If you are a technical person, never accept career guidance from someone who cannot do your job. Period.
Technology is about action, and doing things. Its not about identity. HR in the modern zeitgeist, from big corp to startup, typically avoids having to participate in any action of company product-building by instead promoting identity-as-service.
That this gets inverted is a huge cause of technical debt, imposed by nonsense policies and scripts that do not have a place in technological realms, but rather drama theater.
But that's okay, I could as easily dismiss you with the rationale that you are probably a HR person, as you seem mostly interested in psychology and not the very real, counter-productive problems one might encounter were one to work in the technology industry.
Most of measurement - if at all possible - is much less obvious with technical debt. And inability to easily quantify it, opens up door for corruption.
Yes, and since it's not readily quantifiable, any notion of something analogous to a payoff schedule is not possible. This makes it difficult to make a concrete and specific case for doing code cleanup or debt paydown often just before it's absolutely necessary.
If you challenge someone’s larger architectural decision that is the root of most of the problems, now you’ve entered dangerous territory. Usually, the defense will try to reframe the issue as ‘practical debt’ of the kind I described above. ‘We needed to do this, we thought it was the right way to go, you get it right?’ - not really, no. Those decisions are handicapping the team.
Technical debt is the number one contributor to quality of life imho. Good design that isn’t over engineered on one extreme end, or duck tape everywhere on the other extreme end, can help developers withstand everything the project throws at them.
When a developer can easily understand and make meaningful changes to your codebase within an hour or two on any given day, they can withstand any type of siege (business shifts, design shifts, bugs, users, life). When the debt is too big, any one of those things can break the technical debt dam. It’ll be obvious when simple design changes can’t be made, or when a developer can’t adjust their workload down (will appear slow), or when new developers take time to make an impact (will appear dumb), or when the business changes and the product needs 5 new features that get push back (business will perceive friction).
If we agree to disagree on tech debt then we’ll all pay the price.
- fixed price was paid, software delivered, nobody else cares == it is not a debt;
- fixed price was paid, software delivered, but more potential buyers == tech is most likely in a debt as you'll need to accommodate more changes;
- subscription based income, software needs constant improvements == tech is most likely in a debt;
- VC based income, software needs constant improvements == tech is most likely in a debt as you do not know what you're building;
- no income, software delivered, people want more == dunno;
- no income, software delivered, devs say it is crap == no tech debt;
I think debt should be tightly linked to the potential financial gains. But not only it is hard to quantify it, developers are not usually participating in the financial projections. Because of that you get a speculation on the importance of various refactoring exercises that do not yield any income improvements. Besides developers are usually biased towards improvements because otherwise they (devs) are not necessary anymore.
An outrageous example. Imagine you are painting a naturmort. If you're not careful enough and do not do it right from the beginning it might end up being shit and beyond repair. But who cares if nobody buys it.
My version of tech debt is anything about the design, implementation or operation that isn't meeting the current needs and is not readily adaptable to meet them--an impediment/mismatch in the original design or implementation to what would be a suitable design/implementation now.
Another common thing I've seen with most projects that take on significant amounts of technical debt is a chaotic team structure that is constantly in fire fighting mode. While there are times when you are working on a throwaway/POC/low funded MVP for a startup where it might be appropriate to take on that debt, I have seen far more instances of people using the rationalization of "All of these practices are great, but (we don't have time, money etc. etc. etc.)" when in reality, to achieve the end goal everyone is looking for they are actually omitting non-optional things and shooting themselves in the foot.
It doesn't help further one's career. It feels bad, like a dead end. You're always far behind the curve, and you always feel like a third class citizen behind the whims of management. It goes directly against why most ambitious software devs became a software dev in the first place.
On backends that comprise a database and an API layer on top I find that the sweet spot of speed + iterability can be found by deconstructing the product into its atomic parts. This boils down to modelling the database so that is as close to "reality" (as seen from a business/legal perspective rather than the product's perspective.) as is comfortable.
Reality is somewhat immutable (compared to a product.) Deconstructing (not just necessarily normalize) the API entities into small parts that reflect some "real world idea." The product is an abstraction of "reality" and that abstraction may change, but the underlying parts do not.
Of course once performance comes into account things may be different, but speed is rarely an issue when we start.
* Technical debt is a result of a mismatch between technical architecture and business needs (this comes from Ward Cunningham, the originator of the concept, the OP says)
* OP wants to analyze this mismatch in two main categories:
1) The technical architecture was wrong from the start, as a result of not understanding the business requirements (domain) accurately enough. He calls this "wrong design". (While the OP doesn't say so, I think you could further subdivide this -- you thought you understood the domain but had some misunderstandings; or you knew you didn't understand the domain sufficiently, but had to or chose to proceed anyway to be good enough for now).
2) Originally there was a good match between technical architcture (design) and business requirements (domain), but the environment changed, you have new requirements/demands that didn't even exist in original implementation. He calls this 'rapid evolution'.
In fact, I think those categories can overlap -- the landscape always changes, part of good design is attempting to predict some of that change. This is the trick with software design in general, you are always trying to plan for future needs, and trying to predict the future is always inexact.
Still, these categories seem useful to me conceptually anyway, even if not an exact bifurcation. Some technical debt (design problems) seem more like one or the other.
OP says for the first category "bad design", you reduce it by spending more time understanding the requirements/domain.
For the second category, "rapid evolution", you write code that is easier to refactor. Ah, sez me, but there is the rub, that's exactly what's hard, writing code taht's easy to rrefactor! Especially because it requires predicting the future itself, everything is easy to refactor on some dimensions more than others, requires trying to predict the tthings likely to be invariant vs the things likely to change.
Still, I think these are some good guidelines, it's not really one or the other, think about how much you can invest in both these paths -- understanding your domain better (which really means what kinds of changes are likely in the future), and making code easier to change, even in ways you didn't predict.
But if we want to use technical tech as a tool practically, we should be able to quantify the technical debt precisely.
We should be able to say I have 10 000 € per day or 100 000 € of technical debt.
I have developed (very early stage) a tool to quantify technical debt : I appreciate any feedback (if stated kindly :p)
How about "rust" or "cruft".
Re: inertia, a lot of old code has no speed at all, which is kind of the point here. Inertia implies stasis as much as speed. If you wanted to emphasize speed, you could use "momentum", I suppose.
But I think the idea of inertia, and inert code that requires energy to change, is a more useful analogy than debt.
"A system has technical debt when the effort needed to keep it fit for purpose is surprisingly high. Zero technical debt means that according to our current knowledge, cost of foreseeable future work and maintenance is the lowest possible."
However, those dirty practices that the author dismissed really do pile up and drag you like debt. If you don't deal with them, they get worse until you bust. If those things aren't technical debt, then what are they?
https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
This has too much on how technical debt is generated and use a poorly selected set of quoted terms to reach a bad conclusion.
Technical debt is the ongoing price you pay for making trade-off decisions in design and implementation.
Code management trade-offs? I hate to see all those day. Quality trade-offs? Yup. Customers tell me about those. Security trade-offs? Fix those when you find 'em before bad guys do. Requirements trade-offs? Maybe I can change requirements and package up some of that debt as a requirements-backed security. Go for it PM.
Some come from hastiness, some come from lack of skill. Some come from changing environments and requirements.
Good news: you can avoid all technical debt if you do nothing. Bad news: all decisions are trade-offs.
But tech debt sounds more benign, so they prefer that term...
Though there isn't a Right way, there are right ways in the sense that they have undesirable effects that are less severe and slower growing than the wrong ways.
Personally, I am absolutely against any kind of debt. It has served me well, but has also given me a humble lifestyle. On the other hand, I worked for a 100-year-old Japanese corporation that was (and still is) ferociously debt-averse. In my own life, I feel that my debt-aversion has been a great asset. I'm not so sure that debt-aversion was as good for the corporation I worked for.
But then, "good" is relative. They are 100 years old. That's pretty badass. They got to be 100 by being risk-averse, and building on a robust foundation. But they are also relatively small. Their aversion to debt meant that competitors passed them by, in Ferraris, while they were chugging along in their trusty Volvo.
Often passing flaming, expensive wrecks...
But I digress. It also made it a huge pain to develop software for these folks. I feel as if there was so much design (that yellow curve), that the software suitability suffered.
I consider tech debt to be anything that we say "We'll deal with that down the road." It's really that simple. It may be high issue counts, inflexible design, usability issues, resource usage, cost to maintain, etc.
The word "debt" has a lot of shame attached to it. When I first got married, we needed to use a significant portion of our wedding presents to pay off the credit card debt that I brought into the relationship. That was something that caused me great shame, and was a principal motivator for my "live humble and debt-free" philosophy. I have never carried a balance on credit cards, since. So I have a ridiculously high credit score, but I probably would have a hard time actually borrowing money (so I'm told. I haven't actually tried -the mortgage for my house, and leasing cars has never been an issue).
But debt can also be used as leverage to grow, or do more.
"Tech debt," as the author states, is also often assumed to be the result of "poor code." There's a lot of really badly-written code out there, but much of it is relatively debt-free, due to being tested, encapsulated, and well-maintained. It wasn't allowed past the velvet rope, until it had cleaned up its act.
I've also shitcanned dependencies that had well-written code, unit tests, eye-candy Web sites, and great presentation, but suffered serious bugs.
To me, "debt" also includes things that are not necessarily "loans." For example, stock purchases or investment is not always done as a "loan," legally. That said, I still consider it an obligation (so..."debt").
That's why defining tech debt as anything "that we'll handle down the road" works best for me. Covers a lot of ground, and removes the emotional baggage.
Usability and localization are some things that have resulted in a couple of bent-nose guys telling me how it would be a shame if anything would happen to my kneecaps.
Usability, in particular, is a killer. I have designed, implemented, then removed, some pretty fancy widgets, because they proved to be nice on paper, but unsuitable to my needs in practice. An example is my RVS_Spinner widget[0]. It's a solution, in search of a problem. My RVS_Checkbox widget[1], on the other hand, has proven to be marvelously useful.
When it comes to usability, in my experience, there's absolutely no substitute for actually putting the code out there, and letting people play with it. Early beta-testing is crucial, and I have found that it's also important that the code be full ship-quality; not lash-up-test quality. That's because, if Management likes the demo, it becomes ship code; whether or not I want it to be so. The downside is that, if rejected, I toss out ship-quality code. Sometimes, I may keep the code, and polish it up for future use (that's one reason that I have so many small module packages out there).
Localization and security, in my experience, are things that are easy to manage, if baked in from the start, and a fang-toothed nightmare, if added after the fact. This means that not dealing with those from the start, is a fairly obvious example of "I'll deal with that down the road," that I can live to regret.
Since leaving my last employer, I have been experimenting with what I term "ultra-agile" development techniques. I despise tech debt, so I am trying to figure out how to get "the best of both worlds." The results, so far, have been promising, but my scale is, by necessity, fairly small.
But that's just my experience. YMMV.
[0] https://github.com/RiftValleySoftware/RVS_Spinner#readme
[1] https://github.com/RiftValleySoftware/RVS_Checkbox#readme
First objection: Managers and Business persons understand Debt, like it and use it. I use credit cards and have a car loan. If we, as engineers, present the problem as "You can have what you want now, but you will incur Technical Debt" then any sane person will say "Sure! Good deal!" Ask yourself, how many times a manager or business owner has asked "What is the interest rate?" Zero times.
Even if you really want to call it Debt, don't. Even if you could convince me that Debt really describes the problem, I would suggest that you don't use that term. You are using it because you want to better describe a problem and reach an understanding, and achieve a goal. However, the managers will listen to what you said, agree that it describes the problem, and the proceed to go in the exact opposite direction that you wanted. Calling it Debt does not achieve your goals. You can keep calling debt because it's oh so clever a phrase, but see where it gets you.
Second Objection: It's not debt.
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.