Dependency Injection

When you have different objects and services that does different things and developed by different teams how do you connect them becomes an issue.

DI is a design pattern that aims to decouple object from their dependencies. Instead of creating their own dependencies internally, object receive them from an external source. By using DI we can configure as needed at runtime; with DI dependencies injected at runtime rather than at compiling.

Dependency injection works together perfectly with SOLID principles.
Single Responsibility Principle - DI can help you isolate responsibility of class.
Open-Closed Principle - With new functionalities we can inject new dependencies instead of changing code base.
Dependency Inversion Principle - Dependencies depend on interfaces instead of concrete classes.

There are three types of DI: Constructor Injection, Setter Injection and Interface Injection.

I will give examples as POJO classes, this pattern can be applied to any language and there are solutions in Spring and .NET.

I will build an awesome(?) music lister that lists your musics from particular artist.


This is maybe ok if only i will be using this class and will not make any changes.
In real world with new requirements, we may have to search musics on JSON file or database etc.
We might have dozens of these kind of services in our application.
Our MyMusicLister should not be coupled to some specific implementation, instead it should work with any implementation even we think there wont be any different requirements in the feature(there will be).
We should abstract using of these services with interfaces(and adapter if component isnt designed with an interface).



Now our MyMusicLister no longer coupled/depends on a specific implementation, makes it flexible. If we wanted to test it, we can inject mock finders. We can change dependency at runtime. And our code is more modular.


Benefits of Dependency Injection Design Pattern
Loose coupling: Instead of letting objects create their own dependencies, when you inject dependencies to object you make them more independent.
Maintainability, Scalability and Extensibility: Makes it easier to track, replace, add new requirements, update existing ones without hassle of huge refactoring.



Note: https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not `null`. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency.


 

References: 

Patterns of Enterprise Application Architecture Book by Martin Fowler

https://martinfowler.com/articles/injection.html
https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html