Wednesday, August 27, 2014

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

For some time, I wanted to write something about this topic. it was largely due to my laziness, until now.  well. I guess I overcame my laziness today, and took the effort to get to this topic…


in most of program we write, there are always 2 parties involved, namely provider and consumer. when you write a method which instantiate another class and invoke a method of the instantiated class,  the code you are writing is the consumer, and the class you are instantiated is the provider. the same class in different context could switch its role between consumer and provider.  however, there is one common characteristic between the consumer and the provider, that is the consumer have the control and calls the provider.

Inversion of Control ( IOC) is a mechanism by which the control been transfer to the provider, in another word : let the provider take the control.  the over all goal of IOC is to break the dependency between the consumer and the supplier and yet let them communicate freely. if you take a closer look at the IOC implementations, you will find there are a few different implementation of it. I am going to list them below and give some of them some more detail elaboration on some of them:


Delegates

most of modern programming language supports Delegates, with the exception of Java.  if you look back at any declaration statement 

People myManager 

People is a class defined somewhere else, myManager is a variable can take any instant of People class. 

in 

DayEndOperation myDayEndOperation 

DayEndOperation is a Delegates defined else where, and myDayEndOperation can take in any instance of DayEndOperation

like in the class case, you can invoke the method or property of the class by myManager.Name or myManager.Approve ( yourRequest). in the case of delegate, you can invoke the delegate. you can pass around the delegate as parameter. This is very important as you create a delegate from consumer class and pass it to a method of the suppler class. and let supper class decided when and where to invoke it. 

Event 

Event is a special application of Delegate.  the suppler class defined certain events, when the consumer class instantiates the supplier class, the consumer class get to defined event handlers to react to these events. in the course of execution of the suppler code, the supplier class fire up certain events and in react to the firing of the event, the consumer’s event handling logic get executed.  the key is the supplier took over the control and calling the supplier code. underneath any event handling mechanism, you will see a delegate as part of implementation.


Dependency Injection

Dependency Injection is a mechanism to break the dependency from the consumer to the supplier by introducing Interface.  in this case, 2 more players got into the picture other than consumer and supplier,   ISuppiler and  container. in compiling time, consumer only depends on ISuppiler instead of the solid implementation of ISuppiler. in runtime, container injects the solid implementation into the interface. the injection could be done in code, or by configuration. when it is done in configuration, that means, in run time I can switch the solid implementation of the interface without recompiling the consumer code. This characteristic make it very good for doing coded unit test, because I can inject some stub implementation into my test method to test my consumer code without calling the real supplier components. there are constructor Injection, Property Injection and Method Injection. most of DI container support all of them.  I personally worked on Unity and NDepend.

Service Locator

Suppose your consumer classes have dependencies on an external service , whose concert types are specified sty compile time. The following limitations are posed to the system:
 1. to replace or update  the external service, you need to update your project reference and recompile the solution
2. the external service must be available at compile time
3. your class is difficult to test in isolation because it need the external service to run


Service Locator pattern introduce another element, call <Service Locator>  and let Service Locator handle the dependency of the external service.  in detail implementation, you could inject different locator to your consumer project, or you inject external service into your Service Locator  or you use Factory Pattern to handle the instantiation of the external service.  if the service provider provides respective interface of the service, DI is preferable, otherwise use factory pattern. this preference is due to the fact, only doing DI you will remove the dependency of concert type of the service and only when the interface is provided, you can do DI.

No comments:

Post a Comment