|
Code doesn't deteriorate... Like we're talking about a banana growing spots or whatever... Code gets plastered over with features and abstraction layers, but that's an active process that we are complicit in doing. More germane for this discussion, technical debt was originally defined as a positive thing that you want to go get... It is the mismatch between our domain model and how our users think about the domain. It is positive because “enough with all of the planning and interviewing and requirements gathering and careful architecting, can I just build something and have my users criticize it and do four or five drafts until I get it right?” ... The debt is the drafts before you get it right, the interest is the constant translation between the language of your users and the language that the system is expressed in. You have a “contracts” table that contains things that are not contracts because every purchase foreign keys to a contract, but your users have since wanted to know what they do with the purchases that are not associated with any contract, where do they go. And now every query that aggregates over contracts needs to exclude the non-contract contracts, this is part of the interest you are paying. But at some point it started to mean that we had to upgrade our dependencies, that's tech debt, or this kludge that I threw in, that's tech debt, or the fact that we never worked out a shared library between the front end and the back end and so any Python code in utils.py needs to be manually kept up to date with a file utils.js in a separate Git repo so that we are sure that we can do these things both on the front end and the back end. More broadly, anything that we no longer care for is tech debt. And that's where you really get this idea that it is deteriorating, that's more a measure of our own patience deteriorating, especially as we never seem to have time for the refactors we want. Perversely the cause of not being able to refactor has nothing to do with tech debt and cannot be solved in this way. It's multifaceted so at different places it emerges in different ways, but usually it's an incentive problem. At some places it is that the only incentives are for feature development. At other places it is that every developer is working on a different thing rather than prioritizing one thing that the business needs and delivering it, and allowing developers to use their slack time in this equation to improve the product however they see fit... In yet another it is because the team lead resists any suggestion that the framework being used is too heavyweight for the problem being solved and so trying to keep these very clean abstraction layers is causing people to have to rewrite the same basic thing in five different unrelated places, because it has to bubble up from the data layer into the service layer into the business layer into the controller layer into the API into the consumer layer into the app state layer into the frontend model layer... |
It kind of does -- if you leave a codebase alone for a long time, and you come back to it later to upgrade a lot of dependencies (sometimes making a multi-version jump), it's a lot harder than it would have been to keep them updated as new versions were released.
It would have been a lot worse if that log4j CVE had been in a library with a lot more transitive dependencies or makes breaking changes between versions, like Jersey.
One advantage of monorepos with shared dependencies is that even the parts of the code that don't need to be touched very often will still get the latest dependency updates. If those codebases are in standalone repos, they just sit there, and then one day a simple attempt to upgrade a dependency turns into hours of work.
So, it's not technically "rotting," but it's definitely the case that leaving code to sit creates more technical debt later on -- even if that code was perfectly good the last time anyone worked on it.