Here is one of the very talked about concept: Ioc (Inversion of control). I have been using this concept for a quite some time now. Usually I go for DI (rather than service locator) approach to implement IoC in my code. Below is my understanding of IoC.
If classA is depending on classB if it declares an instance of classB inside it. It's being dependent on classB, is by some reason (I will come to that later), not good and hence we use DI to fix this. So now we have an interface called IClassB that will be passed in classA's constructor (I am taking up constructor injection here, for illustration). Here goes the code:
public class ClassA
{
IClassB _classBObj = null;
public ClassA(IClassB classBObj)
{
_classBObj = classBObj;
}
public void UseClassBMethod()
{
this._classBObj.classBMethod();
}
}
public class ClassB:IClassB
{
public void classBMethod()
{
//Some task carried out by classB.
}
}
public interface IClassB
{
void classBMethod();
}
And here goes the code that makes it go running:
class Program
{
static void Main(string[] args)
{
//This code is outside of class A and hence declaring
//object of ClassB is not dependency
ClassA classA=new ClassA(new ClassB);
classA.UseClassBMethod();
}
}
I have demonstrated the above example just to ensure if my understanding of IoC and DI is correct. If you find anything wrong please do correct me. Now, while I tried to find out why IoC, I found two important reasons:
Testability: Certainly a correct concern. Lets assume, in the above example for instance, classB method makes use of SMPTP server or some WCF/Webservice, we may not be able to test it. We can however create a test stub class implementing the interface IClassB and go ahead with testing by passing an instance of the test stub class.
Dependency in terms of concrete impementation: This is something I could not get along with. Even if I alter the code of classA with the following code:
public class ClassA
{
ClassB _classBObj = null;
public ClassA()
{
_classBObj = new ClassB();
}
public void UseClassBMethod()
{
this._classBObj.classBMethod();
}
}
How is IoC helping to get rid of any problem that arises because of change in the classB Method of the ClassB object? If there is any change in the method signature we will have to make that change in the interface IClassB's method signature too (this in fact, is increasing the refactoring task.). If the method implementation changes say for instance it takes up an additional task of logging, the change is going to be limited to ClassB code.
I may appear a bit stupid with the question but can somebody present a scenario where (apart from unit testability) we are getting benefited by this approach?
Thanks a lot for reading this.