Inversion of Control and Dependency Injection are two buzz words you always hear but may have never understood completely? Here is a tutorial for dummies!
Inversion of Control and Dependency Injection are two of these big buzz words you always hear when talking about modern software development. At least they were when I started going professional. That’s why I invested quite some time to research that topic. I was surprised our Senior Software Engineer did not…
I had to explain it to him while reviewing some of my code. I still remember his reaction:
That’s it? That easy? I was completely mystified by that stuff for years and you just explained it to me in a short call?
If even my valued colleague, who was my mentor for the past few years, still didn’t get that concept, I thought it might be worth to write yet another explanation:
Inversion of Control and Dependency Injection for Dummies!
Let’s say you want to write a piece of code that tracks how much time you spend in front of your computer. You might come up with a simple API like this:
If my colleague implemented that interface a few years back it would have looked somehow like that:
Simple and straight-forward. The only thing this class needs to do its work is a
The class needs an instance of
The class is dependent on a
Stopwatchis a dependency of the class
So far, so good. Now let’s just do a little modification to that code:
The only thing that changed is the constructor.
Instead of creating the instance of
Stopwatch inside the constructor we inject it into the constructor.
We inject the
Stopwatchinto the constructor.
We inject the dependency
Stopwatchinto the constructor.
We just did a dependency injection.
And I just want to make it clear: That is really all! Dependency injection means nothing more and nothing less than providing a dependency to someone who needs it instead of letting the someone create the dependency itself.
It does not matter whether you inject the dependency via the class constructor, via a property, or via a setter-method. All you do is injecting a dependency.
To quote my colleague again:
I think we have to discuss this. Now I need to create the
Stopwatchinstance before I can even create an instance of
ComputerTimeTracker. That sucks. Isn’t that a code smell? Object oriented programming always praises information hiding, but now I have to know about a
Stopwatch? When I create the instance inside the constructor I just have to create my
ComputerTimeTrackerand it will handle the rest for me. I don’t want to know the implementation details, I just want to use the class. In summary: The
Stopwatchshould be controlled by the
Notice how he already used the word controlled. I’m just gonna think that thought a little bit further:
In the approach of my colleague we have clear order of control:
ComputerTimeTrackeris controlling the
It’s the responsibility of the
ComputerTimeTrackerto control the
Now notice what changed when looking at the approach where we injected the
We, the users of
ComputerTimeTracker, are controlling the
It’s the user’s responsibility to control the
You might have already noticed it. By injecting the dependency we inverted the order of control. We moved the responsibility to control the
Stopwatch from the class away to the user of the class. That is inversion of control. And again: That is really all!
Now that the buzz words are de-mystified we can talk about why we might prefer the approach with dependency injection. Let’s enhance our sample code a little further:
All I changed is swapping the class dependency
Stopwatch for an interface dependency
IStopwatch . That way the class
ComputerTimeTracker is not depending on the class
Stopwatchof the .NET framework but loosely coupled to any instance that implements the interface
IStopwatch . Now to our biggest benefit:
All dependencies we inject into a class via an interface can be mocked. That is super convenient. Consider the following use case:
- You start the tracking
- You spend 42 hours before the computer
- You stop the tracking
- You check the spend time
Writing a unit test for that use case is hard when the
Stopwatch instance gets created inside the constructor of
ComputerTimeTracker . You can’t really replace it. And when you can’t replace it you can’t control the
Stopwatch . So you would have to wait real 42 hours. With dependency injection you can simply inject a mocked
Stopwatch into the class, just for the test.
Dependency injection and inversion of control are important concepts every developer should know. They are a little hyped and often misunderstood. But if you invest some time to really dig into it you see how dumb easy they actually are.
And why are they so hyped at all? For me just because they enable me to write readable unit tests for my code. This already sells it for me.
But there are more benefits I did not cover here: Dynamic replacement of dependencies or usage of an IoC-Container. But these are topics for a separate article…
Are there concepts that you just don’t get? Let me know! 🙂
Thanks for reading!