Last year there was some discussion about the relation between a dependency injection container and a service locator. Up until now, developers struggle to use a dependency injection container without injecting the container itself. It happens quite often I point them out to a blog post explaining more in depth the reasoning behind containers and locators.
Because I collected a nice list of resources about this problem, I wanted to share it so more people could learn from it.
A hands-on post from Chris Hartjes gives you clues how to refactor towards a code base where you use dependency injection. Then the code gets transformed using the service locator pattern. He explains why it then becomes an anti-pattern. For Chris, "the difference is in how you use them". Read the post at DIC vs. Service Locator.
Adam Brett summarizes the discussion with the tagline Tell, Don't Ask. Just like Chris, he's stating "the difference between a Service Locator and a Dependency Injection Container is how you consume them". With the Tell, Don't Ask principle, he explains the difference:
People have such a hard time telling the difference between the two because they're really the same thing. The only distinction is that one is used in a way that violates the Tell, Don't Ask principle, and the other is not
In a great post from Anthony Ferrara, known on-line as ircmaxell, he's making a triste against service containers. An analogy is made between global variables and service containers; and everybody knows global variables are bad right? In a thorough and theoretical way, properties of a global variable are juxtaposed to the properties of a service locator (or, service container). How to do it right? Use dependency injection!
At Qafoo, Tobias Schlitt calls the usage of ContainerAware even harmful. "ContainerAware is the new Singleton", he tweeded and the article gets to this point more in depth. The
ContainerAwareInterface is an interface which allows you to use the Service Locator pattern. The pattern leads to issues: "Accessing the DIC in your classes can seriously harm maintainability and code re-usability in the long run". The alternative is "to make your controllers services" or in more general terms, use proper dependency injection.
Tobias wrote the article specifically in Symfony 2 terms (with "ContainerAware" and applying dependency injection by making them "services"). Therefore, Paul M. Jones wrote a short note about this terminology and suggested to say "Service Loction" instead of ContainerAware. His experience from Aura:
Real DI has been a huge win.
To shine some light on the matter from another perspective, Ralph Schindler does not agree the service locator usage pattern should be avoided at all cost. He emphasized "this is not a pattern that should be applied carte-blanche to all code" but there are situations where a service locator is justified. For the following situations, Ralph argues the service locator is a viable solution:
- If a component has many dependencies which are not shared by all workflows within that component;
- If a component has many dependencies and the dependencies tend to grow over time;
- If there is no importance to announce component dependencies upfront by known mechanisms (constructor injection, setter injection, interface injection).
The last one to mention in this list is from Mark Seemann. The often referenced article demonstrates the service locator anti-pattern by C# code. Fortunately the code is very readable for those who know PHP. In my opinion he got the crux of the problem, as he faces the problem towards users of your code. If your code consumes a service locator, "[i]t will give consumers of your API a horrible developer experience".