Dependency Injection Explained

By | June 26, 2015

This is going to be a short c# based tutorial on Dependency Injection.
Newcomers find it difficult to grasp concept of Dependency Injection. I will attempt to explain in simplest terms possible.

As usual, I will deal first with “WHY” and then the “HOW”.

WHY

It is all about removing dependencies from your code. In other words, these help you to decouple your components.

Decouple what?
In caveman simple terms, it means that one software module does not know about other module.

There are many benefits.

1 – When one module changes, other modules need not be changed. Code refactoring made easy.
2 – The module is reusable because it is standalone. It can be plugged in with minimum fuss.
3 – It is easier to test modules which do not have dependencies.
4 – If all this does not help, think of LEGO. You make a structure out of LEGO’s. Each LEGO piece is a software module. The structure is your software solution.

legoBlock

HOW

We will start off with a sample.

Here we see that BatmanBattery and TeslaTuner implement the IBattery and ITuner.

Here is Radio class that uses these two components.

And here is client code.

Do you see a problem there?

The Radio class now knows about BatmanBattery and TeslaTuner. If these classes change then your Radio class gets affected. Suppose a new tuner called TallyHoTuner is in the market. Now you have to update the Radio class if you want to use the new tuner.

Unit testing of Play() method of the Radio is now difficult. Your unit test code will execute code from BatmanBattery and TeslaTuner class (Constructors). Your unit test is not just covering the Radio class. It has code from BatmanBattery and TeslaTuner class also in its scope.

Now let us make some changes

What have we done here?

We now pass the Battery and the Tuner object to the constructor of the Radio class. This simple act has actually done quite a lot.

  1. Notice that now Radio class just knows about the interface and not the implementation.
  2. BatmanBattery and TeslaTuner can be changed at will. No need to recompile the Radio class.
  3. The end user can pass object of any class to the Radio. Provided the class implements the interface Radio class expects.
  4. Now in unit tests you can actually pass on the Fakes implementing the IBattery and ITuner interfaces. This means that now you test only Radio class. This is BIG win in my books.
    To put this in context, I had to unit test login service which used LDAP. LDAP can return many error codes which deal with cases like Login Expired, Change your Password, Account locked and what not. There was no real way I could have done that with company LDAP server. Setting up my own for unit testing was not feasible. So I created a LADP mock which returned these error codes and used it. Smooth.

Dependency Injection can be achieved in 3 different ways:
1 – Constructor Injection – Most common
(The above examples are dependency injection achieved via Constructor Injection)
2 – Setter Injection – Not so common
3 – Method Injection – Rare

There is also something called interface injection but frankly speaking it is not worth mentioning. If you implement “Program to the interfaces” then you are good. In all the three types of Dependency Injection I am illustrating, I am working with Interfaces only.

Constructor Injection
It is a simple way of creating objects. You pass all the dependencies your class needs to the constructor of the class. It helps in testing. It can become a bit tedious when the class has too many dependencies. You have already seen the implementation in the examples given till now.

Setter Injection
In this the dependencies are exposed as the public members of the class. A parameterless constructor is used to create the object. Then the properties are directly set. The previous example reworked to reflect Setter Injection is below.

This method has some issues.
– You “might” forget to set some of the needed properties. And compiler will not give you any warning.
– If the order in which the properties have to be set matters then you have got one more way of failing. An out of order property initialisation.

Method Injection.
This is still rarer form of Dependency injection. Sometimes you have a class in which only one method needs that dependency. In that case that method is passed the dependency directly leaving rest of the code untouched.

Let us rework our radio again.

Many people often confuse Dependency Injection with Dependency Inversion Principle. That will be subject of another post.
If you have time then I recommend that you have a read through this excellent article by Martin Fowler on this subject.

One thought on “Dependency Injection Explained

Leave a Reply