Dependency injection and Service Containers
A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern." Dependency injection is an advanced software design pattern and applying it will increase flexibility. Once you wrap your head around this pattern, you will be unstoppable.
A practical example of accessing services in objects using dependency injection
For the following example, let's assume we are creating a method that will use the service of A, we need to pull the dependencies of B and C into the plugin which we can use to inject whichever services we require.
- Application needs A so:
- Application gets A from the Container, so:
- Container creates C
- Container creates B and gives it C
- Container creates A and gives it B
- Application calls A
- A calls B
- B does something
Types of Dependency Injection
There are different types of Dependency Injection:
- Constructor injection
- Method injection
- Setter and property injection
- PHP callable injection
The DI container supports constructor injection with the help of type hints(Type hinting we can specify the expected data type) for constructor parameters. The type hints tell the container which classes or interfaces are dependent when it is used to create a new object. The container will try to get the instances of the dependent classes or interfaces and then inject them into the new object through the constructor.
In constructor injection we saw that the dependent class will use the same concrete class for its entire lifetime. Now if we need to pass separate concrete class on each invocation of the method, we have to pass the dependency in the method only.
Setter & Property Injection
Now we have discussed two scenarios where in constructor injection we knew that the dependent class will use one concrete class for the entire lifetime. The second approach is to use the method injection where we can pass the concrete class object in the action method itself. But what if the responsibility of selection of concrete class and invocation of method are in separate places. In such cases we need property injection.
PHP Callable Injection
Container will use a registered PHP callable to build new instances of a class. Each time when yii\di\Container::get() is called, the corresponding callable will be invoked. The callable is responsible to resolve the dependencies and inject them appropriately to the newly created objects
Dependency Injection: Advantages & Disadvantages
Reducing the dependency to each other of objects in application.
Unit testing is made easier.
Promotes re-usability of code or objects in different applications
Promotes logical abstraction of components.
DI increases complexity, usually by increasing the number of classes since responsibilities are separated more, which is not always beneficial.
Code will be coupled to the dependency injection framework.
It takes time to learn
If misunderstood it can lead to more harm than good
Dependency injection is a very simple concept of decoupling your code and easier to read. By injecting dependencies to objects we can isolate their purpose and easily swap them with others.
The service container is basically there to manage some classes. It keeps track of what a certain service needs before getting instantiated, does it for you and all you have to do is access the container to request that service. Using it the right way will save time and frustration, while Drupal developers will even make it easier for the layman.