The biggest lie we tell ourselves in software architecture is that we are building for the future. We sprinkle in design patterns "just in case," spin up microservices for a feature that will never scale, and create abstract factories for objects that have exactly one concrete implementation today. I have a strong opinion on this: over-engineering is the real technical debt. Maintainable code isn't about being clever with architecture; it's about being boring. If you can't explain your system's design in a single tweet, you've already lost the maintainability battle.
The moment you introduce indirection for the sake of "separation of concerns" without a concrete requirement, you force the next developer to jump through hoops just to understand the flow. I've seen teams spend weeks refactoring perfectly working code into a labyrinth of interfaces and dependency injections, only to realize that the business logic never changed and the abstractions added zero value. Cognitive load is the enemy of maintainability. When a simple if/else is wrapped in three layers of strategy patterns, you aren't future-proofing your code; you are actively punishing anyone who has to debug it at 2 AM.
So here is my rule of thumb: write code for the today, not the maybe-tomorrow. Apply YAGNI ruthlessly. Start with a monolith, a script, or a simple class, and only abstract when the concrete implementation hurts. If you find yourself writing an interface with a single implementation, delete the interface. Maintainable code is code that can be understood in five minutes, changed in ten, and deleted without fear. Stop building cathedrals and start building sheds—your future self will thank you.
Top comments (0)