The three keywords from the title Dependency Inversion, Inversion of Control and Dependency Injection are fundamental to be understood by any developer. In this article we will take a close look into them – there are NOT the SAME. At the end, I collected a list of articles recommendations.
The Dependency Inversion Principle is part of SOLID and defined by Robert C. Martin:
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend upon details. Details should depend upon abstractions.
How to implement this principle: use interfaces instead of concrete classes! An example (taken from wikipedia): Traditionally modules would be written and they would depend on each other directly. All of them would not be loosely coupled.
Following the dependency inversion principle we use interface to separate between direct implementation and interface. Using the interface we now depend on abstractions.
BUT: it has to be an informed decision and you have to really think about the dependencies and the abstraction. “Just” adding an interface on top of a class does not lead automatically to loose coupling.
Dependency Inversion only suggest how the modules should depend on each other! Nothing else. IoC and DI will add some more insights.
Inversion of Control (IoC) and Dependency Injection (DI)
Inversion of Controls leads to Dependency Injection. I’ll use DI as an example for IoC. It often refers to the “Hollywood Principle: Don’t call us, we’ll call you. (Small anecdote: Martin Fowler thinks IoC is defined to generic therefore he proposed DI). So instead of “hardcoded” object instantiation in constructors or somewhere else, the dependency should be injected.
There are three ways to inject the dependencies:
- Constructor injection
- Setter injection
- Interface injection
Constructor injection is the most used approach when it comes to implementing the dependency injection. There is one big advantage from my side: construction fails if a dependency was not injected. At least, it fails earlier compared to setter or interface injection, then the called action would fail because it wants to call a method on a non existing object (dependency). Moreover, the dependencies are all given in the “overview” of the constructor signature.
Dependency Injection Container
Usually, a container will be created which handles the injection. This container is application wide used for the creation and assembling of objects. It will manage and resolve the dependencies for a class. How a container can be implemented will be discussed later.
- Martin Fowler: https://martinfowler.com/articles/injection.html#UsingAServiceLocator
- Difference Dependency Inversion VS Injection: https://lostechies.com/derickbailey/2011/09/22/dependency-injection-is-not-the-same-as-the-dependency-inversion-principle/
- Introduction into DI (in german): https://blogs.msdn.microsoft.com/dmx/2014/10/14/was-ist-eigentlich-dependency-injection-di/
- Also DI explanation (in german): https://www.dev-insider.de/was-ist-dependency-injection-a-814452/
- With a nice example: https://www.codeproject.com/Articles/615139/An-Absolute-Beginners-Tutorial-on-Dependency-Inver