I agree. But here are other ways of accretion of code inconsistencies:
- Premature abstractions that are subsequently worked around around the edges.
- Automation built on top of wishful thinking instead of how people actually prefer to work.
- Inconsistent naming and file structure.
- Adopting many advanced or hyperspecific styles and techniques instead of leaning on more basic ones that already solve a problem.
I find it way easier, to go from more primitive, consistent, "inlined" code to more sophisticated abstractions that clearly solve emergent problems at a later point in time, than changing the direction of already factored, high level code.
To me it's a matter of mental capacity and friction as well. This stuff is hard, time consuming and requires deliberate effort. I rather accept that code goes through different phases of maturity and that using and maintaining the actual programs over time, gives me a much clearer path forward than applying patterns and principles in advance on an abstract level.
A caveat here is that many of these inconsistency factors come from adopting third party dependencies. In my experience this is the largest chunk of liability or tech debt.
---
However, a large factor that is often overlooked in these discussions, is also organizational scale. When you have to own and understand things from A-Z you can get away with different things than if you are one part of a much larger team and vice versa.
I'm firmly in the former category, so I have to optimize for being able to take a much larger slice of responsibility. But I can also get away with leaving code in a more raw state for longer. I assume this balance looks different the more people you add to a project or organization.
I think we need to take this into consideration in these public discussions. It's ultimately a trade off and programmers from different backgrounds will have different sensibilities.