9

I understand that the Dependency Injection principle is all about decoupling code. Instead of making new instances in the classes, instead you inject them, which make them loosely coupled.

Now if I have to pass on a set of objects that will be used through several classes throughout my application, I can make a container (commonly called dependency injection container).

That is exactly what i am doing because I have to pass a config object, a logger object, a translator object, etc. which will be used through several classes instances of my application. I am passing the whole container through several classes, even if not all of the classes need access to all the objects within the container. This led me to the following question: what is the difference if I create a global Registry and put the objects in there, then retrieve them like Registry::getInstance()->get('logger'); ? Wether I use a global registry or a dependency container, class isntances will have access to all the objects within the container or registry, even if they don't need to see/access all of them.

Conclusion: What is the difference if I pass a dependency injection container along my classes or a global Registry ?

tereško
  • 58,060
  • 25
  • 98
  • 150
Matthew
  • 10,988
  • 11
  • 54
  • 69
  • As I understand if you are injecting the container into the class it this is service location not dependency injection. – Orangepill Jun 17 '13 at 07:55
  • then what is called a dependency injection container? – Matthew Jun 17 '13 at 07:57
  • 1
    As I understand it Dependency Injection always has the dependency coming from outside the class whereas Service Location can occur anywhere. The bad thing with service locators is that they hide what the true dependencies for an object are. – Orangepill Jun 17 '13 at 08:15
  • BTW, logger should never be a dependency of a class. Instead it should be a [**decoration**](http://sourcemaking.com/design_patterns/decorator). – tereško Jun 17 '13 at 08:15
  • 1
    Everything you've said seems closer to the Service Locator pattern... – MattDavey Jun 17 '13 at 11:35

3 Answers3

7

Note: sometimes people use Registries by different names. The common ones that i have seen as: Locator, Context and System.

Use of global Registry causes your code to be tied to the class name of said Registry. It means that you cannot test your code independently. And the way, how registry is set up, lies to you: you can never know which instance will be required.

It is quite common for people to confuse DI Containers with Registries.

DI Container is not something that you inject into a class. Instead it is an enhancement for factories: it determines that class Foo requires instance of Bar to be injected in the constructor. Then, depending on setup, it either acquires new instance of Bar or uses the existing one, to provide said dependency.

  • In a simple factory you usually have to hard-code the dependencies, that will be injected. In this situation, what factory can build, is limited by "footprint" of class's constructor.

  • When factory uses as DI container, it can produce instances with various dependencies. In this setup, your factories focus on constructing instances that are tied to some specific namespaces (or other high-level) logical groups of classes.

tereško
  • 58,060
  • 25
  • 98
  • 150
  • Is it a true statement that all DICs can be (mis)used as a service locator and that the big difference between thee two patterns is more with how it used vs how it's (Container/Locator) implemented. – Orangepill Jun 17 '13 at 08:11
  • @tereško, reading your answer, should I understand that the registry (or service locator) allows access to objects, and DIC is more like a Factory that knows how to *create* these objects? It didn't make sense then to compare those two patterns and DIC is not an alternative to Registry? Though it seems that you suggests to avoid Registry, in favor to another solution? – Matthew Jun 17 '13 at 08:40
  • I would say that a fully implemented DIC system would use a non-static, non-global registry as a cache for initialized instances. Registry is all about storing objects. DI container is about discovering what requirements a class has for creating an instance. Whether the DI container itself create the instance or leaves it to factory is more a question is preference. – tereško Jun 17 '13 at 09:00
6

I think the point missing here is CompositionRoot .As per DI Principle once you define your bindings in the Composition Root , then you can use the reference throughout the application. That is the value DI Container brings.

As per definition "A Composition Root is a (preferably) unique location in an application where modules are composed together."

I will add that a Composition Root also a unique location where all important decisions about your applications behavior takes place. That is what object to use in what situation.This is the heart of a OO system where interaction between the objects deliver the behavior of the system.

  • If I understood correctly, the Composition Root in a PHP MVC-based application would be the bootstrap or a class near the bootstrap. There I would build my classes and inject their dependencies. But that leads me to one question: in this case I cannot build my components dynamically, as all the dependencies have to be set at application entry point. – Matthew Jun 17 '13 at 15:56
  • 2
    This article answered my last comment: http://richardmiller.co.uk/2011/07/07/dependency-injection-moving-from-basics-to-container/ – Matthew Jun 18 '13 at 07:48
0

I agree with most of what teresko has said and i would like to add some points:

  • If you feel that your services are shared among many different instances then you can register them as Singeltons with the container but then you will have to think about multi-threading if it is an issue for your.
  • Whenever you feel that your back is against the wall in a dependency injection scenario then remember that factories (Abstract Factory Pattern) are almost always the solution.
  • The services you mentioned seem like a cross-cutting concern so i would use AOP techniques to avoid bloating my codebase with those concerns, this will make the code much more cleaner.
Ibrahim Najjar
  • 19,178
  • 4
  • 69
  • 95