Kellan Elliott-McCrea, on the way towards an understanding of technical debt, catalogs the ways we end up with code that resists our efforts to change it:
Therefore the second common meaning of “technical debt” is the features of the codebase we encounter in our work that make it resist change. Examples of features that can make a codebase resist change include: poor modularization, poor documentation or poor test coverage. Just as easily though an abundance of modularization (and complexity) or an abundance documentation, and tests encoding the now the incorrect old behavior can apply a strong downward pressure on change.
A little discussed and poorly understood design goal for code is disposability. Given change, what design patterns can we follow that allow us to quickly expunge incorrect behavior from our codebase? Interestingly it is a much more tractable metric for measuring as opposed to more popular criteria like “elegance”. (a post for another day)
Put that in your thinker. Does something like Strategy or Adapter let you throw out whole classes when they prove unnecessary? Or is that so only when you luck out and chose the exact right axes of disposability? Does a microservice really let you discard codebases wholesale? Can maps and functions free you from intertwingled state and behavior or does it move the resistance somewhere else?
Grumpy, opinionated answers: possibly! Even more possibly! Meh. Very meh.