Dependency injection (DI) is a topic that is not quite easy to understand for beginning developers. It doesn’t help that Google search results show examples of dependency injection with frameworks, which removes showing what is really going on.
When I first encountered the concept of dependency injection, I didn’t know what it was. I was already applying it but didn’t know what it was called. So, I consulted Google to find out and what I got were many examples with just frameworks. It took me a while to get past all the overhead of these frameworks to actually understand what was happening. From the perspective of someone who didn’t know at the time, seeing examples with framework make it appear complex.
So, for this post, I am going to talk about what is dependency injection at a conceptual level. I believe it is easy for you to pick up a framework and use it once you understand what is dependency injection itself.
What Is Dependency Injection
To put it simply, dependency injection is transferring the task of creating the object to someone else and directly using the object after it is created. Let’s put this into a more concrete example.
Suppose you have two classes, A and B, and class A uses some methods of B. We can say that A has a dependency on B.
Without dependency injection, A is responsible for creating B. With dependency injection, A transfers the responsibility for creating B to someone else but still uses B when that someone else provides B. So, now A is no longer responsible for creating B, someone else is and they provide B to A.
From the example, someone who provides B is the dependency injector. It is responsible for creating objects, knowing which classes require those objects, and provide them with those objects.
Inversion of Control — Idea Behind Dependency Injection
The main idea behind inversion of control is that a class should not configure its dependencies statically. Instead, its dependencies should be configured by another class from outside. In another word, a class should concentrate on fulfilling its responsibilities and not worry about creating objects that it requires to fulfill those responsibilities. This is where dependency injection comes into play. It provides the class with the required objects at runtime.
Let’s look at the idea of dependency injection from another perspective. Consider the case where a carpenter needs to put some wooden objects together. The carpenter should not have to worry about creating their own hammer, nails, measurement tools, wooden objects, and etc. The supplies that the carpenter needs to fulfill their responsibilities should be provided to them. Dependency injection in this example is to provide the carpenter with their supplies such as hammers, nails, measurement tools, wooden objects, and etc.
Pros of Using Dependency Injection
There are some benefits to DI, otherwise, there is no reason to use it. So, here are some benefits DI can bring to the table.
- Helps with unit testing
- Extending the application becomes easier since objects don’t need to create their dependencies statically
- Boilerplate code is reduced because the injector component handles the initialization of dependencies
- Helps promote loose coupling
Cons of Using Dependency Injection
Despite the benefits of DI; it is not perfect. So, where are some things to consider when using DI.
- Compile time errors turns into runtime errors
- More complex to learn
- Over usage can lead to issues that are hard to figure out
- Some integrated development environment features may not work as intended such as finding references and safe refactoring
I hope this post was helpful to you. If you found this post helpful, share it with others so they can benefit too.
To get in touch, you can follow me on Twitter, leave a comment, or send me an email at steven@brightdevelopers.com.