As an enthusiastic programmer I tend to get overly excited when I discover a new technique – nails, nails everywhere for my shiny new hammer! It’s not a bad thing. I’ll abuse my newfound technique until I fully understand where it is and isn’t appropriate. Sometimes this takes a while.
Automated Dependency Injection is a handy way to wire the component parts of a system together. But systems are comprised of components at varying levels of abstraction. Some are high-level, domain specific abstractions, whilst others are low-level implementation details.
If every object in a system is given the same level of importance, thrown into a DI container, and made available to every other object, the layers of abstraction become very hard to see. The container becomes a mixed bag of configuration details, value objects, sub-systems and goodness-knows-what-else.
Does a URL (a very specific, low-level configuration detail) really deserve to be sitting in a flat container right alongside a high-level, domain specific model? Certainly not!
It can be difficult to determine what is and what isn’t appropriate for automated Dependency Injection. It depends on the system you are building, and is something that comes with time and experience. I’m certainly still struggling with it on a daily basis.
Here’s a related post on the matter:
Program to interfaces, not implementations. Interfaces decouple us from implementations, they are good, but, as always, there are some subtleties worth considering.
Many languages support explicit interfaces: contracts with absolutely no implementation details. But every object also has an implicit interface – the public methods and properties exposed by that object.
Creating an explicit interface for an object that will only ever have a single implementation is a violation of the DRY principle as the explicit interface duplicates the implicit one.
This happens most often when the interface is large and acts as a “stand-in” describing a class rather than a piece of behaviour. Sure, you *could* swap out the implementation at some point, but honestly, so much of the implementation has already leaked out into the interface that there is very little point in doing so.
Program to interfaces, but remember that sometimes a small implicit interface is better than a large explicit one.
Another related post: