In this article, I am going to explore the principle of Dependency Injection, in a very simple way that is very easy to understand. We will take an example from our daily programming practice.
You can find this original article on my blog, here.
Dependency Injection is a way to resolve tight coupling and create loosely coupled classes.
e.g.
- public class A
- {
- public B b { get; set; }
- }
- public class B
- {
- }
This is tight coupling or dependency, or we can say that class A is tightly coupled with class B.
Let’s see what dependency is. What WIKI says about 'Dependency'
"Dependency (computer science) or coupling is a state in which one object uses a function of another object."
Let's now learn, what Dependency Injection is,
"Dependency Injection is a way to create object dependencies outside of the class that uses it."
You inject them from the outside, and take the control of their creation away from the inside of the class.
For example, suppose we have an order class which has some methods to save the order.
- public class Order
- {
- public void SaveOrder()
- {
-
- }
- }
Suppose, the order class needs to send some notification also, notifying that the order has got placed or something. So, we need to modify the order class.
- public class Order
- {
- Notify ObjNotify;
- public void SaveOrder()
- {
-
- ObjNotify = new Notify();
- ObjNotify.SendNotification();
- }
- }
- public class Notify
- {
- public void SendNotification()
- {
-
- }
- }
There is a problem in our SaveOrder method. So, what we are doing wrong here?
Notify ObjNotify = new Notify(); this line.
We are creating an object of the Notify class inside our Order class, which means the Order class is dependent on the Notify class. This is called "dependency or tight coupling" since we are creating object dependency inside the Order class.
The Dependency Injection principle provides a solution to this issue. The dependency principle says, "Create object dependencies outside of the class and inject it in your class". That's it ! Looks so simple...
Example
Let’s modify Order class.
- public class Order
- {
- Notify ObjNotify;
-
- Public Order(Notify ObjNotifyParam)
- {
- this.ObjNotify= ObjNotifyParam;
- }
- public void SaveOrder()
- {
-
- ObjNotify.SendNotification();
- }
- }
Consuming Order class at client.
- Notify ObjNotify = new Notify();
- Order ObjOrder = new Order(ObjNotify);
Now, we are creating Notify object outside of the Order class and when we instantiate order class, we are injecting the Notify object through Order class constructor.
Is it called Dependency Injection ?
We can say "Yes". We have injected the object dependency from outside the Order call so it is the dependency injection principle. Or, we can say that we have implemented DI.
But still, our Order class is depending on the Notify class, so I think we need to do something more.
Now, another principle comes in the picture, that is, ‘Inversion Of Control’. Both the principles come together for good application design.
Let’s see what WIKI says about IoC -
"Inversion of Control (IoC) is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework.’ Bit difficult to me to understand."
OK. So, in simple words, IoC enforces the DI principle for your components to make them loosely coupled and allow code to abstractions.
Let’s modify our class. We will remove Notify dependency from our Order class constructor to make it work with abstraction. So, create an interface
- public interface INotify
- {
- void SendNotification();
- }
And our Notify class implements this INotify interface.
Let’s change our Notify class.
- public class Notify : INotify
- {
- public void SendNotification()
- {
-
- }
- }
Modify your Order class for abstraction.
- public class Order
- {
- INotify ObjNotify;
-
- public Order(INotify ObjNotifyParam)
- {
- this.ObjNotify = ObjNotifyParam;
- }
- public void SaveOrder()
- {
-
- ObjNotify.SendNotification();
- }
- }
Consuming Order class at client.
-
- INotify ObjNotify = new Notify();
-
- Order ObjOrder = new Order(ObjNotify);
That’s it. It is our fully testified design for DI and IoC.
Benefits of the DI
- Loose coupling
- Centralize control
- Easily testable
- Easily extendable