Wednesday, 8 June 2016

Dependency Injection (DI) and Inversion of Control (IOC)

Agenda
  • What is Inversion of Control (IOC)?
  • What is Dependency Injection (DI)?
  • Ways of achieving Dependency Injection
  • Advantages of implementing this principle
Inversion of Control 
We all have seen our college days, right?



In college, sometimes there are events being organized and sometime boring lectures :( . Just considering and remembering our college days let's try to relate the College and Events with Inversion of Control (IOC).

Inversion of Control

Suppose I have a class say College and another class say TechEvents. As you can see in the preceding figure there are many problems that may arise:
  1. Both classes are tightly coupled with each other. I cannot have a College without TechEvents because a TechEvents object is created in a College Constructor.
  2. If I make any changes to TechEvents, I need to compile or you can say update College too.
  3. College controls the creation of Events. College is aware of the single event that is organized. If there is any specific event to be organized like Weekend FootballEvent or PartyEvent, then there needs to make changes to a College class as College is directly referring to Events.
 
Now I need to solve this problem somehow else we would not be able to have any other Events ever in college.
The solution to this could be to shift the control of events organization to some other place.This we call Inversion of Control (IOC), inverting the control to some other entity instead of organizing the event in College directly itself.
What Inversion of control principle says?
Don't Call Me, we will call you
In other words, the Main class should not have a concrete implementation of an aggregated class, rather it should depend on abstraction of that class. The College class should depend on TechEvents class abstraction using an interface or abstract class.

Dependency Injection
IOC can be done using Dependency Injection (DI). It explains how to inject the concrete implementation into a class that is using abstraction, in other words an interface inside. The main idea of dependency injection is to reduce the coupling between classes and move the binding of abstraction and concrete implementation out of the dependent class.
In Simple words, DI is how one object know about other dependent object which is abstracted.
There are mainly 4 ways of achieving the Dependency Injection.



1. Injection via Constructor
This methodology is already discussed above, where the object of the concrete class is passed to the constructor of the dependent class.
  1. class College  
  2. {  
  3.         private IEvent _events;  
  4.         public College(IEvent ie)  
  5.         {  
  6.             _events = ie;  
  7.               
  8.         }  
  9.   
  10.        public void GetEvents()  
  11.         {  
  12.             this._events.LoadEventDetail();  
  13.         }  
  14.   
  15. }  
As you can see above, the event object is injected by the constructor keeping it loosely coupled. The College class will do his work and if it wants to get the events related details, it will call it in the constructor based on which event he wants to call.
  1. College coll = new College(new FootballEvent());  
Along with this advantage, another advantage is that if there are any changes in events or added some more events then College doesn't need to care about that.

2. Injection via Property

This is the most commonly used methodology where we inject the concrete class by creating a property whose type is of Interface.
  1. class College  
  2. {  
  3.         private IEvent _events;  
  4.         public IEvent MyEvent  
  5.         {  
  6.             set  
  7.             {  
  8.                 _events = value;  
  9.             }  
  10.         }  
  11. }  
As you can see above, the setter of the MyEvent property will take a concrete object and bind it to the interface. My class is loosely coupled from a concrete object. Now any changes to the any type of Event class will not affect my College class.
  1. College coll = new College();  
  2. coll.MyEvent = new FootballEvent();  
3. Injection via Method

In this methodology, the concrete class object is passed through the method parameter to the dependent class.
  1. class College  
  2. {  
  3.         private IEvent _events;  
  4.         public void GetEvent(IEvent myevent)  
  5.         {  
  6.             this._events = myevent;  
  7.               
  8.         }  
  9. }  
As you can see above, I have called the event of college using the GetEvents() method where the type of event is passed as a parameter that is of abstract type. This will help me to add or make changes to events without affecting the College, in other words both are decoupled. This is how I can call the method.
  1. College coll = new College();  
  2. coll.GetEvent(new FootballEvent());  
4. Injection via Service Locator

A service locator can act like a simple runtime mapper. This allows code to be added at run-time without re-compiling the application and in some cases without having to even restart it.

  1. class College  
  2.     {  
  3.         private IEvent _events = null;  
  4.         EventLocator el = new EventLocator();  
  5.         public College(int index)  
  6.         {  
  7.             this._events = el.LocateEvent(index);  
  8.         }  
  9.     }  
  10.   
  11.     class EventLocator  
  12.     {  
  13.         public IEvent LocateEvent(int index)  
  14.         {  
  15.             if (index == 1)  
  16.                 return new FootballEvent();  
  17.             else if (index == 2)  
  18.                 return new PartyEvent();  
  19.             else  
  20.                 return new TechEvents();  
  21.         }  
  22.    }  
In the code snippet above, you can see that there is an EventLocator class between the Events and College that helps us to locate the service without knowing the concrete type. I am just passing the index value in the constructor that in turn calls the third party to locate the event and return it to the constructor. Hence any changes to EventLocator will not affect the College class.
  1. College coll = new College(1);  
  2. coll.GetEvents();  
Advantages of implementing this principle
  • It helps in class decoupling.
  • Due to decoupling, the reusability of the code is increased.
  • Improved code maintainability and testing.