| I'm not sure how I feel about this. What has worked for me is embracing change. Requirements will change, third party integrations will change, front end frameworks, use cases, service providers etc. Everything will change so write (really build) code that tolerates change (IOC, interfaces, etc. Any form of loose coupling you can get away with cleanly). There are of course situations when the one line fix is the right one. But in general, this outlook on short term vs long term changes (knowing when the concrete should become the abstract) is one of the differences between being a programmer and a software engineer (or being a senior and a junior). |
Everything might change. Not everything will change.
I think the problem I have with your principle is that many of the techniques to accommodate change (the "IOC, interfaces, etc" you mention) can have a real and immediate cost when it comes to understanding a codebase, and that's the fundamental sin when it comes to maintainability.
Abstraction and indirection have value, obviously, but on balance I'm with GP; don't add 'em until you actually need 'em. In particular, don't add an interface and a factory and whatnot until you actually have more than one implementation.
This may depend on your languages and dev environment; something like IDEA where large-scale but mechanically trivial refactorings can be accomplished quickly and safely are more suited to KISS than e.g. dynamic languages where tooling is much much weaker.