Dependency injection is a set of software design principles and patterns that enables us to develop loosely coupled code, it is also one of the most misunderstood concepts in the object oriented programming.
When class A uses some functionality of class B, then its said that class A has a dependency of class B.
The main purpose of the DI is the maintainability through the loose coupling technique, here are some benefits gained form the loose coupling:
Services can be swapped with other services, late binding refers to the ability to replace parts of an application without recompiling code
Extensibility and Maintainability
Code can be extended and reused, and the responsibility of each class becomes clearly defined. Finally, adding a new feature is more easy because the structure of code allows developers to understand where apply changes.
DI is an important part of supporting unit testing. Unit tests provide rapid feedback on the state of an application, but it is only possible to write unit test when the unit can be properly isolated from it’s dependencies.
By using DI, developers have the capability to inject dependencies and mocks inside the application code to test a specific part of the application without affecting others.
The Dependency injection patterns describe different ways to implement the Dependency injection inside our application. The most important is the Constructor injection pattern.
You can implement dependency injection on your own (Pure Vanilla) or use third-party libraries or frameworks.
Magento 2 uses Dependency Injection to replace functionality provided by the Mage class in Magento 1.x.
the dependency inversion principle and use abstractions in your code to reduce code dependencies. This means that your high level classes should use the interfaces of low level classes instead of working with them directly.
Using interfaces in your code reduces the risk of incompatibility bugs when Magento changes the underlying implementation of those interfaces. It also lets you focus on what a class does instead of how its implemented.
Since the Magento codebase follows this principle, you can map your own implementation of a Magento interface to a dependent class or service using the di.xml file.
Magento uses class constructor signatures to retrieve information about an object’s constructor dependencies. When a class is constructed, the object manager injects the class’s dependencies, defined in the di.xml file, into the class constructor.
The following code sample highlights the two types of dependency injections used in Magento:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="moduleConfig" type="Magento\Core\Model\Config"> <arguments> <argument name="type" xsi:type="string">system</argument> </arguments> </virtualType> <type name="Magento\Core\Model\App"> <arguments> <argument name="config" xsi:type="object">moduleConfig</argument> </arguments> </type> </config>
In the code sample, the Builder class declares its dependency on the Factory and Menu classes in its constructor. Magento uses the di.xml file to determine which implementations to inject into the Builder class.
In the code sample, the Builder class is also dependent on the CommandAbstract class for its processCommand() method.