[HN Gopher] All code is technical debt ___________________________________________________________________ All code is technical debt Author : j45 Score : 159 points Date : 2023-12-19 10:46 UTC (1 days ago) (HTM) web link (www.tokyodev.com) (TXT) w3m dump (www.tokyodev.com) | jeffrallen wrote: | Hang out with mechanical engineers and it won't be long until you | hear, "best part is no part". | | Best code is no code. | sitzkrieg wrote: | this is why deleting code is so great. a lot easier time than | the MEs too | adolph wrote: | https://www.folklore.org/Negative_2000_Lines_Of_Code.html | | _Some of the managers decided that it would be a good idea | to track the progress of each individual engineer in terms of | the amount of code that they wrote from week to week. They | devised a form that each engineer was required to submit | every Friday . . . ._ | | _Bill Atkinson, the author of Quickdraw and the main user | interface designer, . . . was just putting the finishing | touches on the optimization when it was time to fill out the | management form for the first time. When he got to the lines | of code part, he thought about it for a second, and then | wrote in the number: -2000. . . . they stopped asking Bill to | fill out the form, and he gladly complied._ | datadrivenangel wrote: | The code without code is the eternal code. | | All other code requires updating dependencies. | phpisthebest wrote: | You mean a No Code Solution like PowerApps :) | toppy wrote: | https://github.com/kelseyhightower/nocode | zoogeny wrote: | Early in my career I worked with an engineer more senior than | me who was responsible for performance optimization. He once | told me "the fastest thing you can do is nothing at all" which | was his way of saying it is better to find unnecessary steps to | eliminate rather than making necessary steps execute faster. | StayTrue wrote: | Sure I sometimes say features are assets but code is a liability. | Usually as part of an argument against complexity that some | engineers favor to be ready for speculative future circumstances. | pphysch wrote: | I work with a FOSS product that has millions of lines of C. As a | student, I would have been wowed by seeing these FOSS | contributors each with +100,000 LOC in a single project. Now that | I am more familiar how barely-functional the software is, with | glaring architectural mistakes papered over by literally millions | of LOC, I am more cynical. | | "Contributing" 100K LOC by implementing a bespoke http.c and | mysql_client.c in 2020 is almost never something to be proud of | from a SWE and product perspective. Great for ego/NIH and job | security though. | | "Perfection is achieved, not when there is nothing more to add, | but when there is nothing left to take away." -- Antoine de | Saint-Exupery | ravenstine wrote: | That's the thing. Not making the problem _worse_ is fine and | all, but most projects simply aren 't removing enough. It's | amazing that today's software functions as well as it does, and | programmers today are lucky they can hitch a free ride on | decent hardware. | pphysch wrote: | Yeah. Refactors and rewrites (i.e. removing lots of code) are | risky, but so is having critical CVEs and data loss events | every year because of your insanely over-complicated | architecture that has never been rethought in the past | decade+. | | It's a cultural issue where we think major faults "just | happen" and are not directly tied to prior product decisions, | and therefore there isn't much accountability. | | But if you propose a major refactor, there is no question | about (rightly) where the blame lies. | ravenstine wrote: | Modern software is so buggy, but it's considered the norm. | I was talking to a non-technical person recently about | that, and although they were at first puzzled by my view | that most software is problematic, they realized that they | experience the same bugs I complain about all the time. | It's become so normal that people hardly notice it, but | that doesn't make it better because bad software wastes | human life time whether they realize it or not. | | > But if you propose a major refactor, there is no question | about (rightly) where the blame lies. | | LOL Yep. | | Worse is when the blame lies on the semi-technical | cofounder of your company who, granted, achieved quite a | lot on their own, wrote a barely maintainable mess. Do you | really want to be the one to indirectly point out that his | code needs to be replaced? Haha I think a lot of developers | would rather wait for the Dilbert Principle to kick in so | that the cofounder gets out of the way enough for | significant changes to finally be made. | eichin wrote: | In a thread elsewhere (mastodon, I think?) the idea of using | a Copilot-like LLM as an assistant in _removing_ code was | suggested as * a way to use an LLM with less discomfort about | model provenance (since you wouldn 't be using anything it | _generated_ ) * a way to get over some user cynicism (waves) | about whether an LLM usefully "models" the code. | | Of course, at the time noone thought copilot could actually | _do_ any of that, but it was a few weeks ago and things are | moving quickly. | tomxor wrote: | > Technical debt, as originally coined by Ward Cunningham, is the | idea that you can gain a temporary speed boost by rushing | software development, at the cost of slowing down future | development. | | No! Ward's blog post linked in this very paragraph [0] describes | the original definition quite clearly, and it's not this. | | The term was originally intended to describe the delta between a | programmer's _current_ understanding acquired through the process | of developing the software, and the accumulated implementation | which is based upon a combination of _past_ understanding. | Because writing a program is often a process of discovery and | learning about the problem and solution space, it 's not usually | possible to write the ideal implementation up front. | | It's quite clear In Ward's 2nd paragraph where he describes the | correction of this debt: | | > it was important to me that we accumulate the learnings we did | about the application over time by modifying the program to look | as if we had known what we were doing all along and to look as if | it had been easy to do in Smalltalk. | | What the author is describing is the _modern_ definition that it | has acquired independently, where by programmers knowingly take | shortcuts... this is an entirely different phenomenon, | intentionally writing code in a way that is less than ideal even | based on current understanding. I find the original definition | far more interesting and insightful, but the modern one is | perhaps more reflective of the more common realities of the | pressure developing software in a business today. | | [0] https://wiki.c2.com/?WardExplainsDebtMetaphor | | [edit] | | Despite this error, I do agree with the sentiment of the article, | that too much code is a liability, that features can cost more | than they are worth. | | Ward's definition of technical debt affects the cohesion and | correctness of the code, the idea that if you could tear it all | up every day and re-write it from scratch that it would always | reflect the most up to date understanding, and for moving targets | the most up to date problem, that it be absent of the weight of | past misconceptions or solutions to past problems... aiming for | minimal code makes achieving that state far more viable - these | are complementary insights, so it's a shame the nuance of the | original definition was lost. | 0xdeadbeefbabe wrote: | I had no idea Cunningham was so thoughtful about it. It's a | term used by less thoughtful people in most of my experience. | nirvdrum wrote: | I think something similar happened with the term | "refactoring." While it had been in use by a small community | beforehand, Fowler's "Refactoring" book is what really opened | it up to a wider audience. The book defines refactoring as: | | "Refactoring is the process of changing a software system in | such a way that it does not alter the external behavior of | the code yet improves its internal structure. It is a | disciplined way to clean up code that minimizes the chances | of introducing bugs. In essence when you refactor you are | improving the design of the code after it has been written." | | The book then goes on to describe the methodology and runs | through common refactorings step-by-step. Nowadays the term | is used almost generically for code improvement. I'll see | commit messages like "refactored the API", which violates the | edict to not alter external behavior. | | Languages evolve and so on, but it's remarkable to me how | quickly precisely defined terms (or even new words) change | their meaning in tech. My cynical take is it's easier to get | management to buy into "assuming technical debt" and | addressing it with a "refactor" later than it is to "cut | corners" and "rewrite" the code later. As long as everyone | understands the new definition I guess there isn't even | anything wrong with it, but it's a shame we've then lost a | term for the original meaning. | wavemode wrote: | > Refactoring is the process of changing a software system | in such a way that it does not alter the external behavior | of the code yet improves its internal structure. | | That's the meaning of refactoring that I typically hear, | tbh. | | I guess it just depends on what one means by "external | behavior". Changing a function signature changes the | external behavior of that function for callers of that | function, but not for other modules. Changing the interface | of a module changes its external behavior for other modules | depending on it, but not for clients of the whole server. | Changing an API changes the external behavior for the | client, but not for the end user (to whom API changes are | invisible and irrelevant). | | Traditionally, one might say "if the tests still pass, it | was a refactor." Though nowadays that's probably not true | either, as business code tends to contain a lot more | internal testing than it used to (which is good! but also | bad). | nirvdrum wrote: | Perhaps my initial selection was too short. I was trying | to avoid copying out whole sections of the book. Overall, | I think the book is less ambiguous than the one | definition I presented shows. The entirety of the text | reinforces different aspects of that definition. | | Fowler goes on to elaborate on the definition in chapter | two, where he presents two context-dependent definitions | (one a noun, the other a verb). The noun form is a | specific type of change and the verb is the application | of one or more of the nouns. E.g., "Move Method" and | "Move Field" are types of refactorings. These are defined | as changes made "without changing its observable | behavior." To further qualify, he states "[o]nly changes | to make the software easier to understand are | refactorings." By way of example, he compares to | performance optimization where he says: "A good contrast | is performance optimization. Like refactoring, | performance optimization does not usually change the | behavior of a component (other than its speed); it only | alters the internal structure." | | Maybe it's just the domain or languages I work with. | Nowadays I never see anyone apply refactorings as | described in the book. I'm sure devs implicitly apply | several of them, perhaps without the rigor presented, and | that's understandable. But, I often see "refactoring" | just as a catch-all for any code change. | | While certainly there are some blurred lines in terms of | what constitutes a refactoring or not, I think Fowler | handles the product/API split fairly well. He adds: | | "The second thing I want to highlight is that refactoring | does not change the observable behavior of the software. | The software still carries out the same function that it | did before. Any user, whether an end user or another | programmer, cannot tell things have changed." | | By stating a programmer should not be able to tell things | have changed, I think we can at least anchor public APIs | as something that should not be adjusted in a | refactoring. Such a change could improve the maintenance | of the software or the quality of the product, but I | don't think it fits the narrow definition of a | refactoring. Admittedly, the part about the observable | behavior of the software not changing can get murky. But, | I think Fowler tries to scope this more at the code level | than at the product level. | wavemode wrote: | Makes sense! I appreciate the clarification. | burningChrome wrote: | This is how the author starts his entire post. | | I would assume if he misinterpreted Cunningham's original idea, | would it then follow that the rest of the article is suspect | considering the original premise is so far off from what | Cunningham originally intended? | ska wrote: | I agree with this history, but don't think the meaning was | acquired independently so much as naturally grew. Ward presents | it in a sort of "optimal development" context, where what we | did last year was the right thing last year, but we know more | now/things have changed and we know what the right thing would | be today. This is definitely happens, but doesn't allow for a | lot of other real-world reasons for this mismatch between the | current and ideal state. | | The effect is the roughly the same though, there is an | impedance mismatch between what you want to do to/with the | system today, and what the system actual is today, and that has | a cost. The work of reducing this impedance is real work, and | can be thought of as "paying off debt". | zoogeny wrote: | > there is an impedance mismatch between what you want to do | to/with the system today, and what the system actual is today | | This is a better conceptualization compared to the idea that | tech-debt is the result of shortcuts or rushed code. Tech | debt arises for a lot of reasons, including shortcuts but not | exclusively because of shortcuts. I've seen tech debt arise | because well-meaning engineers were trying to do things "the | right way". | | I think it is just a kind of entropy thing that we have to | fight against. A lot of confounding factors lead to code that | is hard to maintain and extend. I think it is an unfair | characterization to suggest it is solely because of laziness | or negligence. | ska wrote: | I've used the entropy analogy also. In particular, entropy | always wins in the end. But I do think it weakens the | "debt" analogy to consider it the same thing, because I | like the idea that this is sometimes transactional - a | choice you make for benefit now which has amortized cost. I | think this is a valuable idea that is separable from the | problems of complexity growth, entropy, etc. | | I certainly don't agree with the idea that all technical | debt is due to shoddy work, that's obviously silly. I | suspect that people fall into it because it is easy to | understand. The original framing is more nuanced and harder | to think about but no less in effect. | gav wrote: | To generalize that idea a little, I think about technical | debt being the accumulation of less-than-perfect decisions, | if you consider the decision you made against the best | possible decision that could have been made in hindsight. | | Sometimes that's not making things flexible enough, or too | flexible, or not having all the requirements captured, or | making technical bets that didn't pan out. | tomxor wrote: | > Ward presents it in a sort of "optimal development" | context, where what we did last year was the right thing last | year, but we know more now/things have changed and we know | what the right thing would be today [...] | | Oh I suspect Ward's context was even more idealistic. That | there was a problem to be solved, and there were few to no | moving targets, the only differences over time were in the | programmer's heads as they learned about the problem domain. | | This is not the only factor in software development today, | which is mostly a moving target (although I kinda wish it | was, it's my favourite form of development, a clear goal and | end state to achieve - aiming for maintenance mode on 1st | release, or pretending you are getting a bunch of discs | stamped - and I really like trying to break real world | problems into these types of mini projects, but that's | another story). Perhaps this is why it was inevitable for the | phrase to take on a new meaning, and honestly maybe "debt" | wasn't the best analogy anyway, your "impedance mismatch" is | probably already a lot better as the sibling commenter points | out. | | > [...] but doesn't allow for a lot of other real-world | reasons for this mismatch between the current and ideal | state. The effect is the roughly the same though, there is an | impedance mismatch between what you want to do to/with the | system today, and what the system actual is today, and that | has a cost. The work of reducing this impedance is real work, | and can be thought of as "paying off debt". | | The effect may be similar, but I think it's useful to | distinguish the forces at play. In particular I believe | conceptual mismatches as per the original definition of | technical debt are catalysts of the "other" debts... The | original form of technical debt is the most common attribute | I notice in the vast majority of source: code is accreted, | existing code, existing decisions are rarely questioned with | intention beyond what is necessary to make the next | requirement on the todo list function, and this tends to | result in a lot of unnecessary artificial work and code to | work around the exiting code base - which of course only | makes it even harder to change. | juped wrote: | I think this is right; the chaos of shifting or | contradictory requirements can leave scars on the physical | codebase reflecting this history, and so can attaining a | better understanding of the problem from working on it, if | one isn't careful to refactor (original sense) rather than | adding new hacks on top. But the prescription for | addressing each situation is pretty different. | ska wrote: | > This is not the only factor in software development | today, | | I suspect it is a mistake to think that software | development today is fundamentally different from how it | was practised when he first wrote that. Possible | application of recency bias.. | LargeWu wrote: | Indeed, there's a significant portion of technical debt | that's created with the full knowledge that it isn't the | optimal approach and will incur a cost of maintenance or use, | but might still be the correct tradeoff at the time. | lysecret wrote: | Indeed very insightful thanks for sharing. | worldsayshi wrote: | In other words, technical debt is when parts of the system does | not yet implement the abstractions that align with the | developers understanding of the problem? | | While I don't think we're there yet or maybe not even close, I | kind of feel like this kind of technical debt would be | something that an LLM should be able to help with. Why can't I | point to a piece of code and say "Look at this new code I | wrote, now go and refactor the rest of the code base to align | with it." Or can I? I assume if I tried to implement something | that did this I would hit the context size limit and that would | be it. | jahewson wrote: | In hindsight Ward's choice of the word "debt" may not have been | the right one. It feels more like "legacy code", in that there | was nothing wrong with it at the time. Its impact on newer | parts of the system is to create a "legacy burden". | | Of course if there was something wrong with the code at the | time then it's more of a "proficiency debt" (or burden) where | the shortcut taken was not in the coding but in not reading the | docs and practicing the craft. | nighthawk454 wrote: | yeah sounds more like "design lag", where the software | necessarily lags behind your ideal understanding by some | amount | tshaddox wrote: | From what I can tell, the definition in the link you provided | is precisely what you're saying it's not. He says this: | | > The explanation I gave to my boss, and this was financial | software, was a financial analogy I called "the debt metaphor". | And that said that if we failed to make our program align with | what we then understood to be the proper way to think about our | financial objects, then we were gonna continually stumble over | that disagreement and that would slow us down which was like | paying interest on a loan. | | So indeed, his definition of technical debt is explicitly that | by rushing software development now you will slow down future | development. | | The _specific_ software engineering task that caused him to | develop the analogy was about rewriting some code to | incorporate new learnings, but the analogy itself is clearly | applicable to any software engineering task that could be | deferred to the future (with a cost). | turtlebits wrote: | IME being in the operations space for along time, developers | often oversimplify/ignore non-coding tasks, that is where I | find most tech debt comes from, as the time/resources is not | estimated/allocated ahead of time. | | Corner cutting == tech debt | | Ask any ops person and none of them will tell you they're | content with the state of their infrastructure. | cesarvarela wrote: | Living is dying. | ranting-moth wrote: | You should write a 15 minute-reading blog post about that. Make | sure to do a summary. I think you could use this linked blog | post as a template. | 0xbadcafebee wrote: | Don't you just love clickbait blog articles that make no sense? | HN sure does! | metabagel wrote: | Even if you disagree with the article, I feel like the comments | here are insightful. | ravenstine wrote: | More code means more opportunities for things to go wrong, but I | wouldn't go quite as far as saying that all code is tech debt, | even though it makes for a good blog post title. Looking at all | code in such a pessimistic light doesn't actually seem that | useful. It might be one thing if there were adequate measures for | "good code", but those hardly exist, or are dwarfed by inadequate | measures that are entirely opinion-based. Less code than more | might be as good as it gets, but I would rephrase the author's | "To avoid technical debt, don't write code" as "To avoid | technical debt, write _less_ code " (though perhaps "fewer codes" | may be more grammatically accurate). Code is not bad, and tech | debt isn't necessarily bad either. We code to accomplish things, | and as much as I despise shitty codebases, even companies with a | lot of tech debt often provide a lot of value to both customers | and employees. In fact, I would say that tech debt in and of | itself is no more a problem than monetary debt in real life, | except when it's _not being paid off_ and is _collecting | interest_. We could not only write less code but actually pay off | our tech debts, yet the structure of incentives and most | companies hardly facilitates that. | ska wrote: | I think the author is basically diluting the term "technical | debt" to the point it becomes meaningless. Much of what they are | talking about is the inherent difficulty of managing complexity, | mixed with the difficulty of understanding requirements/defining | features well. | | I think "technical debt" as a term is overused and sometimes | misapplied, but the core idea resonates with many developers, at | least the way it is most often used - which isn't exactly the | original proposal as another commentpoints out. The key part of | it is the analogy with an interest rate. I can decide do put 5k | on the credit card for a last minute holiday, but for as long as | I don't pay that off, I'm paying 20-something percent, every | month, forever. Similarly for example a rush to add features to | hit a demo deadline can introduce brittleness and abstraction | failures into your codebase that you pay for every time you make | changes, add features, do nearly anything. The analogy is that | some of your development is going to be wasted "servicing the | debt" going forward until you fix that (pay off the debt). That | doesn't mean its the wrong move, for the same reasons that taking | on debt can be the right move for a person or business. | sorokod wrote: | Yes, a bit silly this. Code is means to an end, it makes sence | to think of code as liability (maintenance cost, inevitable | bugs, etc .. ) but this must be contrasted with the value it | provides within some reasonable timeframe. | seadan83 wrote: | I don't think the analogy breaks down per-say. Adding features | is akin to adding a percentage interest rate. Some add more | than others, but the cost of adding a feature is sometimes | (often) dependent upon the existing features in the system. | | Coding & story-writing is a good analogy. If you are inserting | a new scene into a large anthology, you need to make sure the | new scene fits with everything else. OTOH, writing a brand new | story does not have this constraint / cost. | | Which is all to say, software is an asset, code is a cost. The | functionality of software is the valuable thing, all the code | to do that is overhead. Thus, every line of code has a cost, | and an ongoing cost that is forever then payed (which is | exactly the interest; simply taking the time to scan/read over | a line, to scan between 5 files vs 20, those are all ongoing | costs) | ska wrote: | I disagree. Scaling things up has a cost, but not all costs | are debt financed. I think the distinction is worth drawing. | bgirard wrote: | That's a good response. I can buy a house cash, I can buy a | house with a 5% mortgage, or I could buy a house with a | 20+% loan. | | Rushing out features with known bugs, poor architecture, no | test and no documentation is akin to buying a house with a | 20+% loan. You'll get your house sooner but you'll spend | most of your resources servicing that debt until you can | pay it down. | JohnFen wrote: | > I don't think the analogy breaks down per-say. | | Sorry for being "that guy", but I think you meant "per se". | crazygringo wrote: | Completely agreed. | | The idea that "all code is technical debt" because all | requirements could hypothetically change someday, makes as much | sense as saying "all currencies have no value" because 1,000 | years from now we might not be using any of them. | | Technical debt is not defined in terms of possible _future_ | requirements, it is defined in terms of _current_ requirements. | Code that elegantly and concisely expresses current | requirements is debt-free. Code that is a mix of elegantly | expressing old requirements, with new requirements expressed in | a hacky fast way, has debt. | | But trying to judge code in reference to _all possible future | requirements_ is utterly nonsensical. You can 't measure that. | It's literally meaningless. | | So no, all code is not technical debt. Technical debt is | technical debt, and clean code is clean code. Trying to | redefine words to mean their opposite helps no one. That way | lies madness. | posix86 wrote: | But dept can only recognized if you're trying to implement | something new, and notice that you have to pay interest. | Poorly written code makes it very hard to implement new | features & debug existing one, while well written code makes | it easy. So the current dept can only be estimated with | respect of features you are implementing in the future. | majikandy wrote: | Seems fair to assume that "current requirements" means | current roadmap of requirements. Taken to extreme, if there | are no future requirements at all, there is no technical | debt. | chuckadams wrote: | My brother coined a term that I really love: "feature karma". | He's an actual Buddhist, so he used the term "karma" not to | mean a simple score with only positive connotations, but as | something you're chained to and must work off should you at | some point want to move past it. | CSMastermind wrote: | I often try to explain the concept of Technical Wealth as the | other side of the spectrum from Technical Debt. | | Technical Wealth pays dividends; Tech Debt charges interest | on which the payments will eventually become unwieldy. | | That doesn't mean you shouldn't take on Technical Debt, like | many startups do with real money you can and should go into | debt in order to get your business off the ground. But just | like irresponsible financial management can kill your | company, so can irresponsible technical management. | Phiwise_ wrote: | Absolutely agreed. Articles in this vein rather get my goat, | especially because the analogy to real debt is _more_ clear: If | someone wrote a consumer finance article like "All purchases | of things other than cans of beans and Certificates of Deposit | are like Mortgages, because what if your industry collapses | tomorrow?" most people have the good sense to complain that the | usually decent advice of saving a bit for a rainy day was being | way exaggerated. And yet pieces that run something like "All | programming of things other than washing machine | microcontrollers are like technical debt, because what if your | customer's needs suddenly change entirely?" get much more play. | Sure, disasters _can_ happen, and it pays to reserve some | resources to be ready for them, but it also pays to use | resources when times are good to expand. It seems to me | Cunningham 's point was to _encourage a move towards_ balance; | headlines that don 't overshoot the mark. | j45 wrote: | Well said. | | Too often code is a proxy for complexity being added | unnecessarily, consciously or unconsciously. | | Premature optimization or over-engineering or burning your | innovation points on shiny object syndrome can create technical | debt in a different way than just taking shortcuts. | NoPicklez wrote: | I agree and I can't stand it when people dilute terms to the | point they become meaningless. I see it in other areas as well. | | It isn't a profound thought to take a term like "technical | debt" and just say well that's just everything. | | Technical debt is absolutely that, adding something that incurs | a level of interest, until you take the time to pay it off. In | life, we often always have a level of interest to be paid. | | It's a good analogy | rjzzleep wrote: | Almost ten years ago I had the unfortunate opportunity to | work with a master manipulator who was unfortunately more | senior in the hierarchy. | | Most of his code was actually technical debt. The code that | wasn't was external code he integrated. All of the code he | wrote would eventually break down and until it did world | force you to work around it, so it wouldn't fail from | interfacing with it. | | In one of the standup's i used the term technical debt to | argue for fixing one of these issues that broke later but | which he discouraged everyone to fix. | | After that he integrated the term into his daily use to the | point that it became meaningless. The people that believed | this snake oil salesman thought that he had already carefully | weighed his own decisions in advance. | | Needless to say the issue was not fixed before he left the | company and cost millions and plenty of customer headaches. | mmcnl wrote: | What I don't like about "technical debt" is that it's usually | interpreted as "technical" debt: it's only a problem for the | developers, the techies. You immediately lose the business | stakeholders once you start talking about technical debt. But | the problem of technical debt if a problem for everyone, not | just the devs, because it is reflected in quality and time-to- | market. I feel having that conversation about time-to-market | and quality with business stakeholders is incredibly important | and is often skipped. This in turn alienates business | stakeholders from the developers, which is counter-productive. | | So yes, the core idea of technical debt resonates with | developers, but not with business stakeholders. So if you | really think the business is going to be okay with "we're gonna | slow down our time-to-market and say no to all your requests | for a while because we need to pay back our technical debt" | (which is something I see happening over and over again), | you're just keeping them out of the loop and taking over their | responsibilities without actually having their accountability. | Developers shouldn't decide whether time and money should be | invested in time-to-market and quality or feature delivery, but | that's effectively what's happening when business is not | involved in the tech debt discussion. This only leads to | friction and suboptimal results. | | That's why I think we really need to be careful when using the | words "technical debt" and not just label everything we don't | really understand or think can be improved as "technical debt". | Challenge yourself: what really is the problem with this piece | of code, other than that we don't like it? | convolvatron wrote: | unless its a perfect shining jewel - every piece of existing | code constrains future development, until progress | asymptotically approaches zero and development cost | asymptotically approaches infinity | ljm wrote: | I think it _could_ make more sense if it 's rephrased to 'all | code is a liability'. | | Then the equation is simpler. More code = more to maintain = | more liability. It says nothing about the quality of the code, | just the quantity. | | Tech debt is a trade-off between near term and long term | ambitions - it is literally impossible to build a successful | project without accruing this kind of debt, simply because you | cannot perfectly anticipate the future. In that sense, it's not | so much debt as it is a maintenance overhead. | code_biologist wrote: | I agree with the general sentiment but would generalize to | "all corporate surface area is a liability" and that | liability can be minimized in many ways. | | An illustrative example where more code is a lesser | liability: I work on a product with an activity feed feature | built in 2018-19. There was a political battle on whether to | build it internally or use a third party "feed as a service" | product. The build it internally folks won. The "FaaS" under | consideration went under during the pandemic, so we dodged | that bullet. We also have customized it in ways not possible | with an off the shelf product, with no big rewrite necessary. | | On the flipside, we've never had time to implement things | that are trivial with commercial FaaS like iOS and Android | push notifications. Trade-offs are hard! | opportune wrote: | Agreed, or similarly: all software has a carrying | (maintenance, but I think that has connotations of not | including full ongoing TCO) cost. Code is a liability in the | sense that it has a non-zero carrying cost. | | The ideal software implementing a given functionality has as | low of a carrying cost as possible. More code, in quantity | and complexity, typically means more carrying costs. | | One of the appeals of SAAS is that this carrying cost is easy | to quantify and predict. Going further, for high-quality OSS | projects like the Linux Kernel, the carrying cost may be 0 or | close to 0 for most users. But lower quality OSS or buggy | SAAS has a carrying cost in the form of bugs (possibly | affecting downstream users), patches, need for support + back | and forth. | | In this analogy tech debt is a tradeoff for some short term | benefit (like simplicity, time to market) at the expense of | higher carrying costs down the line. But some carrying costs | simply can't be reduced - you can't mooch off something like | the Linux kernel, get your own carrying costs all the way to | 0, or find a SAAS provider/vendor willing to give you the | software for free. So in this model not all code is technical | debt. | smallnamespace wrote: | 'All code is a liability' is also not a particularly accurate | application of finance jargon. | | A car or a house also have ongoing maintenance costs, but | they would normally be classified as assets (because they | generally produce value in excess of the maintenance, or | because you can sell them in a secondary market). | | I think an accurate, useful, but not very catchy rephrasing | is just 'working code requires ongoing maintenance'. | andrewprock wrote: | And all code is an asset. Have we just reduced the | conversation to: everything has a cost, and everything has a | benefit? | matheusmoreira wrote: | I agree. Technical debt is a very useful concept and it's not | helpful to dilute its meaning. | | Only a couple days ago I decided to change some data structure. | It was needlessly hard because I had neglected to create an | accessor function and was instead accessing it directly | everywhere. Had to change every bit of code that accessed the | structure's fields. | | _That 's_ technical debt: something the programmer should have | done but for whatever reason didn't. I paid back the debt by | doing it: I created the function. Now if I want to change the | data structure I only have to update the function. If I hadn't | paid it back, it would start accruing interest: it would be | even harder in the future as more and more stuff accessed the | fields. | iraqmtpizza wrote: | Please sign the rights to all your technical debt over to me. | Thank you. | anonporridge wrote: | All wealth (negentropy/complexity) creation creates debt. | | Whenever we build, we use intelligence to rearrange things in | more complex ways that don't naturally occur. Ideally, this | creates value by unlocking things we want that we previously | couldn't have. | | But this work always creates a burden on the future (debt) to | maintain the complexity we built. This is especially true if the | complexity doesn't gracefully degrade back to a more primitive | state and the choices of people coming after you are "maintain" | or "collapse and regress back further than your predecessor | started, because you've forgotten the old ways". | | If you don't want to place this burden on the future, then the | only surefire solution is to not build anything. Just be happy | with maintaining what you have and hope that the environment | doesn't change around you so much that what you have isn't good | enough. | | But I don't think this is what we want. We need to build a LOT | more for some of the existential goals we have as a civilization. | | Just know that every act of creation that sticks around | intrinsically creates a burden on the future to maintain it. | | Acknowledge and respect that, but keep building. | anonporridge wrote: | Addendum; | | A concrete example of this conflict that I've been wrestling | with recently. I've been considering going all in on home | automation. Zigbee devices and sensors everywhere managed with | custom rules on Home Assistant. I want to get to the point | where I don't ever have to touch a light switch. | | However, I also recognize stories of others who have done this, | and then died leaving their less technical spouse with an | unmaintainable mess that gradually degrades and falls to | Entropy. They eventually have to hire someone to rip it all out | and revert to a dumb house. | | By going all in on home automation, I'm creating debt for | future me and my partner to maintain it all. At the moment, I'm | not convinced that this act of creation will actually create | enough value to justified the debt incurred. | flerchin wrote: | This is exactly why I haven't automated my newest house. All | the automation in my last one was net-negative to the buyer. | captainkrtek wrote: | I like to think of technical debt with a counter balance of a | "credit score". Ie: as an organization, what is our ability and | track record to manage complexity over time. | | It's not a perfect analogy, but the difference between a low | interest rate mortgage and a high interest payday loan have | parallels to the balance made in delivering software while | limiting complexity. A developer that is a bit of a tornado, | rapidly churning out new and exciting capabilities at the expense | of reliability, brittleness, and complexity, will surely catch up | with an organization sooner or later. | jmduke wrote: | I agree with many of this essay's points, but the flamboyant | headline is a reductive way to view software (and a bit of a | dangerous meme.) | | Your job as an engineer is, amongst other things, to identify the | (sometimes rare!) instances in which code creates leverage beyond | the business value it creates. Good abstractions are valuable | assets! | Ensorceled wrote: | > So to give a quick recap, as adding more code to a product will | slow down development, we should view all code as technical debt. | | Not a fan of this habit of taking a perfectly good technical term | and redefining for another purpose; especially if there is | already good, existing measures, such as code complexity. | | Rather, than calling all new code "technical debt", how about | every planned feature, as part of it's total cost calculation, | include the incremental costs of any increased code and/or | architectural complexity it introduces. | mjr00 wrote: | The author is conflating a few different things. | | All code and features are _overhead_. It requires maintenance | when it breaks, or requirements change. It increases complexity | when working on other parts of the system, as other new features | have to ask "how does this interact with existing features?", | even if the answer to that is "it doesn't". At Amazon one of the | VPs had a rule of thumb that if a dev or team worked full-time on | a new feature, they would be at 50% of their capacity after the | feature was "done" for 3-12 months due to ongoing maintenance. | | So yes, writing less code rather than more code for the same | feature is good, generally. But all software requires _some_ | code, so the challenge is figuring out which code is necessary | for which the maintenance and overhead costs are worth it. | | Technical debt is a bit different; the code is there, but | something about it makes it challenging to maintain. There's lots | of reasons this can happen. Sometimes the business requirements | change and the domain concepts or abstractions no longer make | sense. Sometimes the technical requirements change and decisions | made at the time are no longer the right ones, if they were ever | right at all. | | But the most common reason, in my experience, is that the | _people_ have changed. New people have come in, looked at | existing systems and code, and either don 't understand it or | don't agree with how it was written from a personal stylistic | point of view. Like a functional programming looking at a system | that was designed with textbook OOP and calling that technical | debt. | | As you move into more senior technical positions or engineering | management one of the bigger challenges is determining what's | "real" technical debt that's worth tackling, versus what's | perceived technical debt that's based on personal opinions. | metabagel wrote: | And sometimes it can be difficult to tell when a complex | solution is actually appropriate and not a candidate for being | re-implemented. | AndyPa32 wrote: | In a similar vein I always try to convince colleagues that the | best code is the one that is never written. As a close second the | code that has been deleted. It has no bugs and doesn't need | maintenance. | abakker wrote: | Put more directly: all choices are costs. Specifically, a choice | is choosing to incur opportunity cost in order to realize some | outcome. | | E.g. Buying a sandwich so you can eat it to be full is choosing | not to spend that $10 on anything else. | | In durable and intellectual domains, choices can incur | opportunity costs, but also lead to switching costs in the | future. I've always understood technical debt to be the | combination of opportunity costs and switching costs resultant | from a specific choice that resulted in a durable physical or | intellectual good. | | In this way, technical debt is not a particularly complicated | topic. The issue is that switching costs can be very high, and to | eliminate the accumulated opportunity cost and switching costs of | a previous decision, it is necessary to incur a new set of costs | going forward. | | There is no "debt", there is only cost. The idea that you can | "owe" on a series of choices implies that you can "pay it back". | This is false. You can make choices - some may be more costly | than others both immediately and in the future - but all choices | have costs always. To quote Rush, "if you choose not to decide, | you still have made a choice". | knodi wrote: | If all code is tech debt then all employees are liabilities. | marcod wrote: | I mean I have definitely felt like a liability before :p | | "What do you mean, we have to pay health insurance for all of | them?? Let's get the cheapest option available!" | imhoguy wrote: | Well, IT/Engineering as a cost center is everyday corporate | life. | ranting-moth wrote: | Excuse my rule breaking, but holy shit this is crap. | open-paren wrote: | I prefer to say that "code is a liability, not an asset." | Liabilities are useful and help achieve goals (want a house, get | a mortgage), but the code is not the goal. Code is a mechanism | that achieves that goal, but more code becomes a drag. | indymike wrote: | "I prefer my products to have less code in them." -- Can't | remember what smarter person than I said it... | | Conceptually, I think every developer eventually realizes that | every line of code ends up adding maintenance cost, and | potentially constraints on the future. "Technical Debt" is one | way to think about it - if you don't have the resources to | maintain. Otherwise, it's just a cost as others have pointed out. | | Maintenance is harder than most people think: documentation, | translations, tests, all are part of this cost. | erikerikson wrote: | The author should really read Peter Naur's "Programming as Theory | Building". | | [0] https://pages.cs.wisc.edu/~remzi/Naur.pdf | jrockway wrote: | Code is inventory, not debt. Inventory is good and bad. If | someone comes to your store and everything is out of stock, you | will make $0. So you want some inventory. But if you have too | much inventory and nobody is buying anything, then your inventory | just rusts in storage and becomes worthless. Code is pretty much | exactly the same. Most features are sitting in storage in the | hopes that someone comes by to buy it. Sometimes they do! | Sometimes they don't. If you were the guy with a toilet paper | warehouse in March 2020 you did great. | mmcnl wrote: | Code is an asset. Assets need to be managed, maintained, or | else they will degrade. Assets have costs. | thiago_fm wrote: | The correct term is "technical liability". | | I like to dive into a codebase the same way people do accounting | for the finances of a company, the parallels always make sense. | rqtwteye wrote: | I always tell people that deleted code is the best code. | alex201 wrote: | Insightful articulation of the concept of technical debt | (likening it to a financial loan) but it somewhat oversimplifies | the nuanced and often non-linear nature of software development. | I observe that technical debt is not always a straight trade-off | between speed and future maintenance. Sometimes, what appears as | debt could be a strategic decision aligned with evolving business | goals or market demands. The article underestimates the dynamic | nature of software projects where initial assumptions might | change, making the so-called 'debt' a necessary step in the | process of innovation and adaptation. This perspective fails to | acknowledge that in certain scenarios, adhering too rigidly to | best practices can lead to missed opportunities or an inability | to pivot quickly in response to user feedback or changing market | conditions. | jfengel wrote: | Conversely: "The things you own, end up owning you". | | A line of code is something you own. It makes you obligated to | either maintain it or let it go. The only truly free development | is greenfield development, where you can write whatever you want. | And now you've got code you own, and you're in its debt. | | So yeah, we can all live wonderfully free lives by writing no | code, but that does tend to up our other debts, i.e. student | loans, mortgages, etc. | | Good code is not more code or less code but code that does what | the customer actually wants it to do. The better we understand | the customer's needs, the more we can write just the correct | code. We can't always do that; often the customer themselves | doesn't know what they need. | | Regardless, the way out of this conundrum is to stop counting | code, technical debt, or other ways of trying to make the _human_ | problem into a _computer_ problem. The real problems are always | out there, not in our repositories. | fhars wrote: | There is this old notion that you should think of "lines of code | spent to solve a problem", not of "lines of code produced". | veucast wrote: | It's interesting to see someone putting a positive spin to | technical debt. The level of technical debt you can afford taking | on (technical risk) is heavily dependent on how you define | technical debt at your company. You must understand how taking on | a technical risk will have an impact in the current and future | operation of the entire business/product/team. Not all technical | debts are created equal, so to encourage people to see it as a | positive thing or risk worth taking, without giving them this | disclaimer is irresponsible. | otabdeveloper4 wrote: | Nah, some of it is an heirloom. | equalsione wrote: | This is a "when you think about it" argument. As in "humans are | just tubes, when you think about it". | | Technical debt is a thorny issue already. Arguments like this | don't help. | wins32767 wrote: | Code is best reasoned about as a depreciating asset, not | technical debt. | pyromaker wrote: | Ultimately, everything can be debt. If code is technical debt, a | HR system or a process that you implement for the company at that | particular point in time is also a debt (process debt? HR debt? | debt nonetheless). | | If we are trying to deliver fast by expediting software | development and taking shortcuts (technical debt), another | department can also do something similar (quick, our HR process | is slow and cumbersome, implement that HR system) - which would | solve the particular issues for the business at that particular | point in time, but may not the needs of the business later on. | | For software, the issue is that we believe we can introduce | technical debts, that is, it is permissible to introduce and talk | about technical debts. We wouldn't necessarily talk about | implementing a new HR system often. | | We think writing a line of code is fast (and define what "fast" | means) but it isn't. | csours wrote: | Any code _having_side_effects_ is technical debt. Pure functional | code is innocent of any sin. | Nevermark wrote: | Like quite a few people, I find the word "debt" to carry a lot of | connotations that don't seem apply to building non-ideal code. | | For me, "technical debt" would be shipping a product that is | going to predictably require regular investment just to keep | going. Like a distributed database that needs manual work to fix | regular corruptions. | | In contrast, writing code without care for future work is not | some original emergent issue of software development that we | should need to navel gaze about. It is a universally understood, | common sense problem for any foundation work: in design, | engineering, construction, book stacking, whatever. | | It already has 1000 names: "Building on Sand", "Ticking | Timebombs", "Bandaid Solutions", "Cutting Corners", "Short Term | Fixes", "Playing Jenga", "Putting Lipstick on a Pig", "Haste | Makes Waste", etc. I suggest: "Shoddy Foundations". | | Essay Title: _All Living Code is a Foundation_ | | Essay Body: _Don 't build shoddy foundations._ | | There! That's it. Nothing more to say. No new terminology. You | don't even need strategies for how to translate it for the non- | techies. | | Tell your CEO they can get those enormous features yesterday, | they just need to attach their name to a "shoddy foundation" | signoff. Informally by email is fine. You are ready to unleashed | the troops from responsibility for future mishaps! All you need | is that little written record! Then presto! The coders are | standing by, breathless, ready to party! (And preparing their | resumes.) | jrochkind1 wrote: | Whether it is exactly the same concept as actual technical debt | or not... | | This makes a lot of sense to me, and explains why you always | think "I can do better than that monster", and it _does_ always | feel better at first, then then inevitably grows to feel like a | monster where it 's hard to make any changes. | | Especially when we are thinking about _tools for developers_ , | where developers are the users, libraries or web frameworks and | such. Or even languages/ecosystems. A bunch of existing | libraries/frameworks/platforms/ecosystems _are_ a mess... surely | we can do better! let 's make a new thing! | | This explains why we are always hopping to the new thing, and | always convinced the new thing is better... | | And the new thing is better and so much easier to work with, even | though it doesn't have all the features the old thing did, but | okay, we just need to keep building it out to encompass those | features, using our _much_ better sense of architecture and | usability that we 've proven we have because look how clean and | simple and usable our first draft is! | | Now, there is such a thing as better or worse designed, as the OP | admits, poorly implemented or beautifully implemented. But... | comparing the new thing that only has the most basic features and | seems really elegant to the old thing that covers all the edge | cases... isn't actually a good comparison to tel you which is | better implemented. That new thing is going to get cruftier when | you cover the edges, _always_. | | And it shows that if you want to keep your thing feeling smooth | and elegant and easy to work with.. you have to keep it as small | as possible and resist all feature requests! | | > For a feature to add value to your product, it needs to be | useful to users. Features can have a negative value when the | technical debt they add to your product outweighs the value they | add to it. | | Thinking of tools for developers where developers are the | users... _oh yeah_ it 's true. | | > A technique for reducing technical debt when adding a new | feature is to work within the constraints of existing | assumptions, rather than adding new ones | | I would describe that as limiting the number of "concepts" inside | your code... and definitely applies to libraries/frameworks/tools | for developers. | mjw_byrne wrote: | Taking a useful concept and stretching it to an extreme in order | to generate a counterintuitive-but-plausible soundbite is not the | same thing as wisdom. | | Other examples that come to mind are "a complete rewrite is | always a mistake" (no, it just has different risks/rewards), "if | you are reading this part of the docs, you are trying to be too | clever" (your API is too much for my puny brain is it?) and "all | functions are APIs" (no, my two-line string quoting func is not | an API, actually). | lnxg33k1 wrote: | I personally consider tech debt code that is hard to reason | about, change, understand or not covered by unit test. I think | the author just wanted to say something nonsense to go viral and | get share/increase klout, but if the concept of code is | symmetrical to the one of tech debt then the concept of tech debt | is useless and we need something else to scope code that is hard | to be worked on, and back to square one ___________________________________________________________________ (page generated 2023-12-20 23:00 UTC)