14

I am currently writing my own MVC framework for learning purpose and I decided to use a Dependency Injection Container to share common used objects between classes (for example DB instance).

I initialized the container in my bootstrap file and I have a instance of it in my Application class, is it a good practice to pass an instance of the container during the routing process? (i.e. passing container object as a parameter in ControllerBase constructor). Also, is it good practice to accept the container as a parameter in the constructor of my ModelBase?

tereško
  • 58,060
  • 25
  • 98
  • 150
user1365914
  • 858
  • 2
  • 18
  • 32
  • 7
    No what you are doing (passing in the entire thing) is called a service locator and is an anti pattern. – PeeHaa Feb 11 '15 at 17:50
  • The container should never be passed around, and if it's done, then it should only be a lazy-loading detail. To clarify, you should never have to write anything related with the container when testing any of the classes involved in your MVC setup, regardless if you are mocking it or not. – Ocramius Feb 11 '15 at 17:52
  • 1
    I have written an answer about using globals which has many of the same problems as a service locator a while back. Although it is not an exact answer to your question it is worth a read and certainly relevant to your question http://stackoverflow.com/questions/11923272/use-global-variables-in-a-class/11923384#11923384 – PeeHaa Feb 11 '15 at 18:01
  • @Ocramius if I can't reference the container from outside my bootstrap file, what's the point of it? How can I access (for instance) my DB object that is stored in the container from either Controller and/or Model? – user1365914 Feb 11 '15 at 21:37
  • You'd just pass it ("it" being the DB object) to Controller/Model/Whatever. – Ocramius Feb 12 '15 at 10:21
  • @Ocramius Then why should I create a Dependency Injection Container instead of creating a DB instance? At the end I'll pass a DB object. – user1365914 Feb 13 '15 at 13:12
  • 2
    Your DIC's goal is to store configured instances of classes (like a DB object) that will be shared among many other instances. If you instanciate manually services every time you need them without using a DIC, it brings many pattern issues. The biggest one, IMHO, is that you create a hard coupling between classes and prevent the dependency (your DB object) to actually be overriden (thus breaking at least the S and L of SOLID). If not already done, I higly recommend you to read this : http://symfony.com/doc/current/book/service_container.html – Gildas Feb 17 '15 at 22:45
  • What you may need to elaborate is a ContainerAware interface wich will be implemented by your controller. It will be the 'responsability' of your kernel to inject an instance of the service container into the base controller class. – Francesco Panina Feb 20 '15 at 17:23
  • 3
    Some MVC frameworks do inject the container into the controller. Symfony has their BaseController implement a ContainerAware interface like @FrancescoPanina mentioned. Laravel on the other hand uses reflection to determine the dependencies of the controller and then injects just the dependencies from the container when resolving the controller. – kylehyde215 Mar 06 '15 at 02:03

1 Answers1

1

It sounds as a Dependency Injector is something different to what you are doing. It sounds more like a ServiceLocator, a repository or whatever. Usually the Dependency Injector is inbetween the call (if you use it for parameter injection) or between the creation (if you use it for field or constructor injection).

The usage of the dependency injector must be completely transparent to the code/object being injected to. So if you pass a reference you do something wrong.

Also the DependencyInjector belongs to the environment your code runs within. See it as it is. The dependency injector should even not be known to the application unless you use the application as being the framework you run in.

So get dependency injection to work means no reference to the injector within the actual application. The goal is to run the application both way with injection or without. Periode.

Martin Kersten
  • 5,127
  • 8
  • 46
  • 77