Many developers say with a sarcastic tone “You can fix any problem with another layer of abstraction”. The question is if there is any truth to this. While abstraction can increase reuse, flexibility and testability it comes with a cost of complexity in readability and maintainability. If a developer has to spend a week learning how all the pieces of an application are put together there better be a payoff. Always ask yourself “what do we gain” when adding a new factory or dependency injection? Is there a proper return on investment? I’m not saying don’t add abstraction layers. Be pragmatic about it.
Every pattern has its place, but don’t overuse them. If the requirement of your application is to be able to dynamically plug in a nearly infinite number of modules then a set of interfaces and a generic dependency injection approach might be the way to go, but don’t start there. If that requirement isn’t there don’t use patterns and abstraction layers because you “could, possibly, maybe” need it at some point in the future. Live by the rule “You’re not going to need it”.
I don’t know how many times I have seen code where there is a layer in between your business and data layer that does nothing but call the data layer and pass it back to the business layer without adding any value. Each piece of code needs to have a purpose. If you can’t explain what that purpose is then you need to refactor it out.
Walk through your code and see how many times you need a cheat sheet to know what object you are referencing or what the business purpose of a piece of code is. If you are confused by your own code you may have gone too far. Have someone else walk through your code and see what questions they have and how long it takes them to understand what you have built.
At some point in the future your code will have to be maintained either for enhancements or bug fixes. Consider how much effort those changes will cost in time and effort. Do those costs fit with the requirements of your business? The lesson I would hope to impart is that abstractions should be used and not abused. Keep this in mind as you design and it may just save your sanity.