The best analogy for technical debt is debt - that is where it got the name from! Just like financial debt, technical debt is not necessary a bad thing, but a tool - and something to manage, control and track. And just like financial debt, taking out too much technical debt without paying it back can crush you.
There is nothing wrong with taking out a mortgage (and thus getting into debt) to buy a house - you just need to understand how to pay it off. Similarly, if you start a startup trying to find product-market fit before running out of money, there is nothing wrong taking on technical debt to do so, as long as you understand what you are doing.
The problem with this analogy is you don't necessarily take on technical debt when you make your technical decisions. Technical decisions only become debt when you have to revisit those decisions. You don't pay interest on debt over time. You pay interest whenever you build upon or modify the flawed code.
You can write the shittiest spaghetti code in the world, and if you never have to build upon - or touch it again - you took on zero technical debt.
In comparison, if you write just slightly flawed design, but build out your complete featureset based upon that flawed design, you could have mountains of technical debt.
I think a better analogy is building a structure. If your code is foundational, you better get that shit right. If you cheap out on a $20 part and have to replace it, but it's just a door knob, that's not too bad. But if it's under your slab on grade foundation you're going to pay thousands to dig it up and fix a $20 part.
* Contagion. How much it spreads over time. If a piece of tech debt is well-contained, the cost to fix it later compared to now is basically identical. On the other hand, some forms of tech debt keep giving. Image if your string type has some issues.
Linking that back to the debt analogy, there are different interest rates for different kinds of debt, depending on how contagious that part of the code is.
The only code you never have to touch again is code nobody is using. In which case, it's like a corporation declaring bankruptcy: the debt becomes moot.
Otherwise, you always have to deal with it eventually. Look at the Y2K problem. or how the 2038 problem is starting to crop up already, exposing significant levels of technical debt. https://twitter.com/jxxf/status/1219009308438024200
I also think technical debt does accrue interest over time, albeit not as linearly as a modern installment-plan debt does. That's because it slowly falls out of sync with people's memories. With libraries, with operating systems, with techniques. Bad code I wrote 10 minutes ago is pretty easy to clean up. But the next day, the next month, the next year? The cleanup gets more expensive. At some point the work becomes more archaeology than normal programming.
It's also true that actual foundations have something in common with foundational code. But that's a different aspect of programming than what tech debt is pointing at.
> Most operating systems designed to run on 64-bit hardware already use signed 64-bit time_t integers. Using a signed 64-bit value introduces a new wraparound date that is over twenty times greater than the estimated age of the universe: approximately 292 billion years from now, at 15:30:08 UTC on Sunday, 4 December 292,277,026,596.
There's a pretty clear ship date, after which you never touch it again.
Even in the world of SAAS, there are plenty of services or libraries that you write that serve a single purpose, are good enough, and never get touched again.
Well, some video games, those based on a historical model of actually shipping physical games. But successful video games these days can literally run for decades, either directly (as Warcraft) or as a series (like Madden NFL). Plenty of things that are intended to be one-and-dones also evolve, like Stardew Valley's audience demanding multiplayer.
Even the code you mention isn't a great example for your case. In theory it was throwaway, but now that it's out there, you can bet that plenty of people will be touching it. And you're also ignoring the path not taken. This beloved game didn't get a sequel, despite plenty of demand. If the code were in better shape, might it have had one?
> You can write the shittiest spaghetti code in the world, and if you never have to build upon - or touch it again - you took on zero technical debt.
I don't really agree with this view; it may seem pedantic, but I think it's better to consider that case as tech debt.
In my experience, it's incredibly uncommon to write code and never touch it again -- particularly if you elect to cut corners in the interest of getting something out the door quicker. That code inevitably either gets retired because it's not being used (your debt was forgiven), or gets built on top of (your debt starts to compound).
If you make a decision to lower the quality bar because "we are not going to touch this again, so it's not tech debt, so it doesn't matter", then I think you're fooling yourself. Instead, I think it's better to assume that you're taking on tech debt (you almost certainly are), apply all the best practices around managing that debt (i.e. catalog it, be aware of your overall debt level, and be aware of tech debt in critical systems), and be happy if your debt is later forgiven if you miraculously never need to touch that code again.
Maybe there's a narrow sense in which this position is technically/semantically correct, but I think more often than not, this position is going to hurt you more than it helps.
> Technical debt consists in performing a fix or development in a quick and dirty way because it takes less time, even though it will make the code harder to work with in the long term.
If you aren't going to be changing the code later, then writing a bunch of spaghetti code won't make it harder to work with in the long term.
How can one accurately predict that the code won't be changing in the future? If you needed to get something done once, isn't there a good chance that in the future someone else, including your future self, may need to rely on or modify it?
It’s contextual. E.g. if you’re in a situation very similar to past situations where you threw the code away afterwards, you can be pretty confident that you’ll throw it away this time too.
The difference though is that financial debt is very easy to measure and quantify but technical debt is not.
I like the Tetris analogy because that game has a type of debt that anyone who has played it can understand, yet is not as easily quantifiable as financial debt.
I guess the analogy still works because not all debt is monetary.
You might owe a debt to the mob. Perhaps they help you out of a sticky situation but let you know that some unspecified favor will be required in the future. So you have a debt, but what exactly you owe is loosely-defined and might cause great chaos in your life at some inconvenient point when it's time to repay.
While I fully agree that financial debt is easier to measure, and some forms of it are very easy to measure, I don't think it is always very easy to measure. Perhaps it may be a difference in what counts as debt, but I see many people engaging in decisions that require future payments without considering those payments at all, much less viewing them as debt. For example, getting a pet dog can have numerous costs associated with it but people don't always consider these as debt. And the average person (fully based on my own personal anecdotes) isn't going to be willing to give up the dog just because it is costing them money. So while there isn't a legal due that you can be taken to court for, I still think it counts as a form of debt.
Then should we talk about technical liability and compare it to financial liability? Maybe that would be a closer comparison than using debt in both cases.
I personally like "deferred maintenance". Similarly doesn't have a monetary value to it, unless you actually do a check-up where you could calculate it (man hour estimations).
That's a good point. I think of any given project as a CDO. There are good, productive debts and bad, stinking, potentially crushing debts in there. What matters is not that there is debt - I think there will always be - but what the blend is.
If the debts were thoughtful and deliberate with understood risks, they might make perfect sense.
If the debts were taken by people who couldn't evaluate them and had no business making that decision, it's going to be bad.
Odds are the first are well-understood and maybe even documented. The second may explode when the underlying assumptions or risk changes.
Sounds like debt to me. With all the refinancing going on I wouldn't be surprised if there's still some debt out there that can be traced back to someone centuries ago that hasn't been payed back yet.
I was going to say the opposite, just because you'll "pay it off later" doesn't mean you're not paying for it now, with every single change taking longer than necessary.
Or the unit of measure. It's really hard to tell what sort of technical debt you are taking on and building for contingencies that may never manifest is it's own type of sunk cost. That's (a) why projects need to have some strategies that move forward without excluding lateral (or minor-backtracking) moves, and (b) why software development is inherently hard.
It's more like a compound interest. A financial example would be payday loans with an incredible APR and a low monthly payment, your debt is forever increasing.
And I might add: what is technical debt in one project, maybe isn't in another project.
Engineers sometimes want to overengineer things that would work just fine in that situation. I remember an old link about someone studying the source code of a game (Doom maybe) expecting to find beautiful solutions for every minor problem when in fact he was surprised by how most of it was straightforward.
Check what needs to scale/be resilient before reinforcing the code there (and of course, if the solution is already frail at the moment it probably needs to be fixed sooner rather than later)
I live my coding life by this philosophy: The best code is the stuff that looks like any novice could have written it, but only an expert knows how hard that is to do.
(bonus: write your code like the next person to work on it is a psychopath and they know where you live)
> financial debt is very easy to measure and quantify but technical debt is not
For business school grad PMs I like to see if they can run with an analogy to selling unhedged call options rather than thinking of it in terms of debt with a known payoff schedule.
Even the bankers got derivatives wrong at an epic scale.
I wonder if there was a time in history where financial debt was not well understood. This would have to be either before the invention of algebra, or possibly also during a time of very poor education.
> or possibly also during a time of very poor education.
So, you mean today? The number of students that take on crippling amounts of student loans without truly understanding how it will affect them is staggering to me. The ease of obtaining credit before a person truly understands how devastating 20%+ interest rates are is also pretty telling. Financial debt is easy to get wrong, and is only compounded by the fact we don't teach this as a basic course in primary schools.
Even worse, many think they understand finances without realizing there is a difference in corporate versus personal financing. The rules don't necessarily transfer between them.
Or just large numbers. A valid strategy to invest a million will be worthless with just a dime. No matter what the silly myths of success say.
A monetary metaphor for technical debt implies a freedom to the order of addressing technical debt that is deceptive. This comes from money's fungible nature: if you have many debts, you can pay off whichever debt you want and you can pay it off in parts.
I think this metaphor does a good job of capturing the path-dependant nature of debt. How the size of each individual debt sits in the shadow of the code that relies on the flawed code. Understanding that there's the work of fixing technical debt and the work of getting to the place where you can fix technical debt feels more clearly communicated by tetris than by financial debt.
Financial debt is a good analogy, but there is a crucial difference: technical debt is not fungible.
Cleaning up one kind of issue in your code doesn't affect other kinds of issues, and you can end up with fundamental architectural problems that no amount of testing or clean up can compensate for. You can handle some issues incrementally (eg adding tests), but some issues are going to be so fundamental to your system that you can only handle them by making a lot of changes all at once.
In this analogy, game development is like taking on crippling amounts of debt, declaring bankruptcy, and then starting a new company to do it all over again.
And just like real debt, you can just walk away from it at any time with no obligation right, not even on your credit rating? Just look at the debt and say "don't want you no more" and the debt says "aw shucks. Guess you don't feel the benefit of paying me. I can understand. So all right.
I won't complain.", and the debt goes and disappears, down some dark alley with a bottle of scotch, no debt collectors ever hound you about it, and you never hear from the debt again.
That kind of debt, right?
But wait there's more! I forgot to mention that even if you walk away you get to keep what you bought on credit, without any further payment of any kind and it continues working in its current state, forever - you just can't improve or renovate it if you walk away from the debt.¹
That kind of debt, right? If so then perfect analogy.
-
¹ literal lie though, yes you can. you can totally still improve it real quick. I'm afraid I'll have to add $150,000 to your technical debt though, which you can walk away from any time. still want this real quick $50 change though? It might be $50 but it's $150,000 in debt though.
Sure, defaulting does decrease your credit rating, as your example of 50 $ change for 150000 $ more in debt illustrates.
And yes, there is a point further borrowing will be rejected, as sibling comments in this thread mention.
So, excluding the actual strawman numbers, analogy still holds very well.
I "defaulted" on the loan of replacing a script I wrote in 2 minutes in autohotkey (a windows scripting language). I'm never going to write it properly.
Now explain to me how defaulting on this technical debt has hurt my credit rating.
Is the next time I open a new autohotkey script is it going to say to me "Now wait a minute. What about all the debt you defaulted on last time? I'm not going to let you write a quick and dirty script! You'll default on ever rewriting it! Go do it properly as a source controlled project in Microsoft Visual Studio. I am not letting you write another script."
Is that what happens? No?
That autohotkey script is running now. Where's the debt? How is my credit rating worsened by defaulting on it?
It's debt you can default on at any time without any consequence, while being able to continue to use what you bought on credit.
Your version is like saying that the minute a squatter takes up residence in an abandoned building, he's just gotten $140,000 in debt, the cost of buying some land nearby and building a proper, albeit unfinished building with no electricity or heating.
And if, still in his abandoned building squat, he finds and burns some wood in the winter, watch out! He's just added $25,000 in debt to the $140,000 he already had, since that's what a proper HVAC system will cost in his properly built building. He went from $140,000 in debt to $165,000 in debt the minute he set fire to some wood.
But that's clearly very wrong. Maybe he'll live in that abandoned building for 4 years and then just walk away. Poof. The $165,000 in lousy-analogy debt disappears the moment he walks away.
In general, I'd agree with that assessment, but the debt-based metaphor also reaches its limits in a couple of cases.
One of which is that it is often really hard to quantify, but that does not seem to stop many non-technical manager types from trying to treat it like financial debt nontheless.
Another one is that unlike financial debt, which should be controlled by various organization-internal mechanisms, tech debt is often not something management is conscious about (at least when it is "created"). I've seen far too many examples of horrible code that can simply be explained with lazyness or incompetence, but I'm pretty sure management never called for a hard to use, unnecessarily complicated API.
Also, if the tech debt is caused by management, it is usually an implicit byproduct of unrealistic time constraints, and I'm pretty sure in those cases they would often choose find another solution too if they were conscious about how bad the problem they're creating really is.
Edit: Either that, or their incentives are way off because they don't have to deal with the consequences. Which is also the real cause why financial debt is usually strictly controlled.
The old 25% rule (don't take a mortgage unless it is no more than 25% of your income) is ignored all the time. My mortgage was right at that, and I generally have never had trouble coming up with it. If I was doing 50-70% like some of my California friends I'd be as nervous as a rat at a cat farm. So I think you have to set some reasonable amount of technical debt as you say. Some issue simply dissolve, others get worse as far as the debt goes. Sometimes the business goes in a different direction and more dissolves. Other times maybe a big deal comes in for one of your products and you realize it might not be as easy to update for new needs (and $$ of income in particular) so you don't want to let it build up too much.
The problem to me is this covers your language choice as a debt. You are literally borrowing against the knowledge in the standard library of your language choice. You may have to leave standard someday based on growth or success.
Most of what people call debt, though, is really just comprises. Which works, to me, as you can just say the code is too compromised. :)
Another thing worth noting is that company success doesn't mean you're more easily able to pay off the debt like you would your mortgage. In fact the opposite may be true and it may limit future earnings if it bites you in the wrong place.
It's a good analogy, but if this is what it took to get through to your PM what technical debt is, I think you should look for another job, stat. This is a core concept anyone with that kind of power over your work hours should understand deeply already.
>This is a core concept anyone with that kind of power over your work hours should understand deeply already.
If the individual(s) with power over ones work have spent time writing code then they will most likely have an understanding. If they haven't then it often takes analogies of this nature to help them begin to understand what technical debt is and how it has an impact on the future of the product.
In this kind of discussions I read the same two or three positions rehashed over and over again that are highly dependent on the situation(s) the wielder of such opinions has found themselves in previously.
One thing I've never seen properly stated is the difference between technical debt as usually described (building code that is doing the job but might not be as flexible, easy to change or fix or might not account for all corner cases appropriately) and then the kind of debt I've experience more often which is "model debt". In the field of business applications, modeling a problem correctly is 80% of the solution, and new companies usually do that job very poorly. Over time as business experience accumulates, some of those mistakes become evident. For example, how to model the identity of the users of an application, that's where the most mindless decisions I've experienced do the most damage. Let's say you assume the only type of user you're gonna have belongs to "companies" and your customers are companies. Then you discover those companies make heavy use of consultants or contractors, and all of a sudden most of your management tools and UI doesn't quite fit. You can hack it, but you end up with a large slice of your users having to manage 20 different emails to interact with your system. Just an example.
"model debt" is the most expensive and potentially fatal type of debt a new piece of software can incur, and my suggestion is for every new project, focus on building a real good model of what reality looks like before too many other technical calls are made, or you're in for a world of hurt.
I tend use the "Leaning Tower of Pisa" metaphor.
If it leans too much, the tower will fall down.
If it doesn't tilt at all, you won't sell tickets to tourists.
I sometimes use a container ship example. Management makes decisions about steering course and that is possible when you have small cargo. If you decided to pile up 1 kilometer tall stack of containers and didn't bother laying some of them down at the port then you'll have damn hard time steering the ship. You have to make sure it doesn't topple over completely by that point.
It's beautiful and also a very important piece of Romanesque architecture. It's probably the greatest example of circular bell tower. I'm sure that if it was not leaning, it would be still very appreciated, maybe not by the postcard turists but surely not considered "like several other towers".
OTOH there are thousands of tourist attractions that are not leaning. So unless the only interesting feature of your software is the technical debt I am not sure how this metaphor applies.
I think the metaphor is trying to say that in real world, things don't always work out perfectly, and you often have to resort to creating some technical debt to make the deadlines for the release. Even if it's not pretty.
This metaphor cannot be stretched too far, though, since the actual tower has the leaning as one of its main attractions, whereas in your project, the technical debt is best hidden from tourists (customers). :)
I agree. In fact I think it's quite a nice high-level illustration of the pros and cons of tech debt.
It amazes me the number of people who think metaphors and analogies are literal copies of the concept they're approximating and thus proceed to nitpick those comparisons.
> The analogy with technical debt is that each new fix or development is like a new block coming in, which you need to integrate with the existing code. If you hack it in a quick and dirty way, it’s like leaving holes in the Tetris structure: you’re making life more difficult down the line.
Like with Tetris sometimes you find a block that allows for retirement of a lot of old stuff. But maybe this block never comes. Or maybe it comes only after you papered over the debt and the solution does not work anymore.
It's not the best metaphor on just the technical debt, but to the whole modern corporate governance, which prefers short term profits instead of fixing things for long term gains.
Fully agree. Refactoring (that serves to reduce tech. debt) needs to happen on a recurring basis. It's the 3rd pillar of coding activity, alongside features, and bugfixes.
Technical debt is risk. Just like in financial systems, taking on SOME risk is how you make money, but you need to measure it and minimize it and be prepared for if the risks taken all end unfavorably. This product risk (see also dependency risk) is intertwined with the combined risk of other projects going on, whether they're public relations risk, technical risk, staff risk, etc. and taking on too much risk means you have too many flipped coins in the air to count on them all landing favorably for you, even if they're weighted.
Tech debt is more nuanced than explained by most analogies.
In reality there is a lot of tech debt you can get away for free and never have to pay back. The code can be a mess but the functionality works and doesn't need updating.
Other tech debt can infect and cripple a system if it isn't contained early.
If you demonstrate that you know how to prioritize the most important tech debt then it is easier to convince management to work on it.
The concept of doing more work now to make future easier is universal. Delivering on it is the hard part.
If it never costs you anything, it's just a design decision, not technical debt. Plenty of projects never upgraded C versions, so old C is maybe not technical debt. But plenty of projects are upgrading python versions now, so old python is often technical debt.
No, there is an important difference. It's technical debt because you might have to pay it back, but it might also turn out that you will be switching directions altogether and in that case the debt gets forgiven.
All code might need to be tweaked though. Even talking about stable C, the toolchain under it might become unsupported, requiring a port. That means every system include and compiler definition is technical debt.
There's a difference between a toolchain becoming unsupported, and putting a hack around a feature that later becomes obsolete due to business decisions.
That hack could certainly be technical debt, up until it isn't. If the code that it was implemented in is no longer used in the future, you didn't incur any cost to it.
Not an original idea but I can't remember where I heard the idea. Technical debt is the best kind of debt, because it's the only debt that you might not have to pay back.
It doesn't have to be a hack to be technical debt. Anything with a shelf life, even out of date design, has risk and costs. The old python 2 is technical debt even if it wasn't a hack. Something needs to be done, it's just a question of what and when.
Analogies create a false sense of meaning. Nothing new is gained other than an isomorphism. There is no logical transfer of new information because the analogy only works if you already understand both concepts. Additionally, analogies may over simplify concepts but usually people are too enamored by the isomorphism to really see it.
Think about this famous analogy: "Life is like a box of chocolates. You never know what you're gonna get."
I clearly know about how life and a box of chocolates can be random at times. This is dead obvious information to the point of pointlessness. Yet in church or in meetings you see people nod their heads in agreement as if something insightful was said. Here's reality: Nothing insightful was said, the person who was comparing life to a box of chocolates is literally mentally retarded.
Isomorphism can yield eye-opening insights and inspire new behaviors. Drawing connections between similar ideas in different domains can be an enjoyable and creative mental exercise.
Yes in this sense it's good. But usually for analogies it's just relating one obvious fact to another obvious fact and the relations are so flush with each other that you fail to see that all you're being told are obvious facts.
>Even if you leave a few holes in, it’s ok if you manage to have compact rows above them that will clear out and allow to fill the holes later. This is similar to technical debt, that is ok to build up if it’s under control and you have a plan to pay it back later.
That's a very low-tier understanding of Tetris. At an intermediate level of play, you'll want to deliberately leave gaps that you could clear at any time, but you choose to wait until it is strategically advantageous to do so.
At an advanced level of play, you'll want to leave oddly-shaped gaps that can only be cleared with a Clever Hack which not everyone is able to understand, let alone perform. (T-Spin)
Similar concepts do exist in programming, they are cynically referred to as "Job Security" but I doubt that the author intended to encourage that sort of behavior.
People talk about technical debt like it accumulates to a point where you can't go on, but as someone who has worked at a company with totally overwhelming, malignant tech debt, teams can and do go on, for some definition of "going on." Don't get me wrong, it is an absolute miserable place to be. It's like a software purgatory, where things "work" but also mysteriously don't work sometimes. Will you be punished for implementing new feature X? Nobody knows--that's for the tech debt monster to decide.
I believe that learning how to identify a team that is drowning in tech debt is a valuable interview skill.
This is an ad for a book on dealing with legacy code. The preview of the book [1] is more useful than the forced Tetris analogy.
Reading the table of contents of the book, it seems to assume everything is done by hand. There are some power tools for dealing with legacy code in C/C++, but I don't know which ones are any good and for what. A book which covered most of them and wasn't a fan piece for one tool would be helpful.
Technical Debt is a term used by non-professionals as a euphemism for their own incompetence. I say this not to cut people down but with all due desire for us to get better at our work.
It's a lot harder for someone to say "I didn't know how to solve this" and much easier to say "It would take longer to solve it the right way." Because of this you should take claims fo "Technical Debt" with serious suspicion -- and given how fuzzy the general concept is and how enabling it is, I think the proper response is to find it useful far more for personal ego management than as a respectable tool for thinking about execution of software projects.
There is no innate conflict between solid decision-making in a software system and execution time. Generalizations take longer but generalizations or lack thereof do not imply sound architecture; this is orthogonal concerns. But solid execution (decoupled components) is a skillset question. In fact if you have the skillset it often takes longer to make a bad decision.
Technical Debt doesn't respect this (i.e. skills/mastery) and is only good for deflecting from our incompetence and thus keeping us from acquiring the necessary skillset.
Implementation technical debt (the code) makes it harder for devs to work in a given service, slows down velocity and increases the risk of bugs, but is at least contained to a given service and can be rewritten as a known quantity.
Architectural technical debt will crush your product or your stack, often quickly.
Technical debt for me means I will have a job fixing it at my current company for many years to come (If I want it).
There will almost always be technical debt to some degree when it comes to software. Nothing is perfect and we always dont have the time to create the perfect fix..and instead need to just create something that works.
I think my favorite analogy for technical debt is uncovered option, which, compared to just technical debt, adds the information that it might or might not be required to pay it back. Of course, to be able to use, your non-coder interlocutor needs to know the relevant vocabulary.
It so happens I’ve been thinking a lot about the debt analogy recently and decided that the simplest improvement is to think of it as an interest-only loan.
Sure, that balloon is just sitting there, but every single day you don’t pay it down, you are still paying interest. It slows you down when it causes confusion, when it makes integration more difficult, and when everyone is afraid to make improvements that might require changes to That Godforsaken Class.
And if instead of paying it down, you decide to add more debt, then the interest payments go up / the drag just gets worse.
And let’s be honest, arguing that tech debt is not bad comes up way more often over adding more than deciding not to start paying down.
Was waiting for the ultimate analogy : Plugin a tetris vertical bar is like a carefully planned ahead refactoring. It's the most effective strategy as it clean out 4 lines of technical debt in a single move.
Every project needs to treat tech debt differently, for example working alone vs working with 20. How many requirements there are already, what state it was in when you arrive to see the code(most devs are not the original coders). How good the unit tests are, how proj Managment sees value in refactoring, company run way if it’s a start up. Is very difficult to apply single analogy to all projects. I see programming like life, it’s different every time so you have to approach refactoring to fit the situation every time
> But technical debt becomes a problem when it gets out of control. Accumulating technical debt consists in piling up hacks on a piece of code, making it harder and harder to maintain. Every incremental change requires an intense reflexion and is more and more likely to cause regressions.
Can anyone explain to me what reflexion means in this context?
Here's the insidious part of technical debt. There's two types:
Known and unknown.
If you are not knowingly accumulating technical debt, then 90% of the time you are accumulating it unknowingly. This is the most insidious form of debt.
I have searched my entire career in software engineering for the solution to unknown technical debt. The problem isn't just solving it, it's also clearly defining what is happening to your software over the years even when you spend the utmost care in not allowing technical debt to accumulate.
I think I sort of nailed down what's going on in a fuzzy way. I also sort of have a fuzzy solution to the problem. Allow me to elucidate:
Eventually most projects will hit a point where you realize that your initial design was poor. You are given a new feature and your old design is simply not flexible enough to accommodate the change. In order to put the feature in, you either do a massive rewrite or you hack it in.
In this way the technical debt that was accumulated unknowingly may force the programmer to begin accumulating debt knowingly. In fact they often forget about the unknown technical debt. They think that the only proper solution is to contemplate between the cost of a hacky shortcut or a massive rewrite without thinking about what caused the need for the massive change in design. What exactly is the thing that is causing the "need" for the massive rewrite?
What's happening is, whenever you design something you are predicting the future. You are assuming your design can handle certain current requirements and future ones. However, the future is actually unknown, there is very little chance you can ever predict the future in an accurate way. Thus by your lack of ability to predict the future, your design will usually in the majority of cases fail to predict the future and this problem will always occur.
That is all that is happening with unknown technical debt.
The best solution (not a full solution) to this is to design all your projects with the maximum flexibility possible. That means every corner of your code that can be factored into multiple modules or be easily factorable in the future. By coding this way, you maximize the reusability and reconfigurability of your code giving the best possible insurance for an unknown future.
If you heard of ravioli code, this is it. It has bad connotations but ravioli code is my best known solution to unknown technical debt. Most people feel ravioli code is hard to read or maintain... In a way it is, but the key here is deal with the program in layers of abstraction. Your complicated ravioli code of 100 primitives at the lowest layer must be able to "compose" into higher level layers where you only have to deal with a manageable 20 primitives.
So the key isn't just ravioli code, but ravioli code with highly compose-able modules you can use to simplify your code into layers. Think of it like a slider between flexibility and simplicity. The higher the flexibility (more primitives) the more complex your program is; the lower the flexibility (less primitives) the more simple your program is... A good design is one where at any moment in the projects life time you can move from layer to layer and readjust the flexibility and simplicity of the program at will.
Unknown to most people there is a programming style that does the above almost mechanically:
Typed Functional programming.
You may have done some FP and seen it get messy (especially with JS), but to really see why this is the solution you should take a look at Typed FP using the point free style. The point free style will help you understand the true nature of a compose-able primitive.
If you work at a startup that is still trying to become profitable and you have a $300,000 deal on a line that is dependent on a functioning product demo by Friday, you rush as fast as you can, and you build it as well as you can in the time allotted. Unfortunately, there often simply isn't enough time and resources available to build it "right". But you manage to get a functioning demo/prototype working and the startup makes the sale and is able to stay alive for a couple more months.
You do everything in your power to explain the compromises that were made to the CTO and the CEO, and they weigh their options and determine that they want to keep duct taping things together as fast as possible to keep making more of these quick sales.
Building things "right" the first time is a luxury that is rarely possible in the real world, I've found. Maybe if you are working at a big company like Google or Amazon? But from what I've seen, even the projects coming out of those companies are often deeply flawed and have have a plethora of issues when they are initially released.
Analogies and metaphors are pointless. Whenever you use them, they'll just respond with their own counter metaphors they pull equally efficiently from their own rear ends, with a tone of indignation, implying you're trying to trick them.
The only thing that works with technical debt is to aggressively uncover and strike down any short term incentivisation from an organization perspective, and to set in absolute concrete terms what the irrevocable code maintenance policy is, and punish those who don't follow it. Everything beyond that, TD measurement tools and TD backlogs (which you interlace at a minimum ratio) are just details.
But the last thing that'll help you is talking about Tetris in front of your client / PO / boss / whatever. Just call it "maintenance work". And if they're hostile to even that, it means they're stupid enough that you can just do it anyway and call it something else and they'll never know.
"Just call it "maintenance work". And if they're hostile to even that, it means they're stupid enough that you can just do it anyway and call it something else and they'll never know."
That is quite true. Unless you are working in a jira ticket sweatshop just do it.
IMO analogies and metaphors can absolutely help build trust across groups which may not yet really understand each other's domains.
They can be highly successful, but from your comment it sounds like you've dealt with managers or clients who simply want to "win the conversation". In that case I can understand why you'd prefer to take care of the necessary remediation more covertly.
Doesn't mean others won't benefit from apt metaphors though - bad collaboration partners sounds the issue here, not figurative techniques per se.
There is nothing wrong with taking out a mortgage (and thus getting into debt) to buy a house - you just need to understand how to pay it off. Similarly, if you start a startup trying to find product-market fit before running out of money, there is nothing wrong taking on technical debt to do so, as long as you understand what you are doing.