Pranay Rana: Dependency Injection
Showing posts with label Dependency Injection. Show all posts
Showing posts with label Dependency Injection. Show all posts

Monday, July 13, 2015

Dependency Inversion Principle

The Dependency Inversion Principle is one of the SOLID principles defined by Robert C. Martin. This principle is about dependencies among the components (such as two modules, two classes) of the software.

The principle says that high-level modules should depend on abstraction, not on the details, of low level modules, in other words not the implementation of the low level module. Abstraction should not depend on details. Details should depend on abstraction. In simple words the principle says that there should not be a tight coupling among components (in other words two modules, two classes) of software and to avoid that, the components should depend on abstraction, in other words a contract (interface or abstract class).

Dependency Inversion Principle in Real life

To understand the second problem better way, let's see a real life scenario of a computer or laptop.




As you can see in the preceding image we have a port for each external device to which I can associate an external device and do our work.

But the problem with this is, I cannot attach my keyboard to a printer port and vice versa. The same problem occurs with the other devices. So this is like a tight coupling, that I cannot change my external device on the given interface, in other words on which I depend.

Solution to this is USB port.

If I have a USB port then I can easily attach any device to my machine and perform my task.



Example of Dependency Inversion Principle in Application Development

The following is a class diagram of tight coupling that does not follow the principle.



Public Class Customer  
{  
    CustomerRepository CustomerRepository;  
    Public Customer  
    {  
        CustomerRepository = new CustomerRpository();  
}  
  
Public bool Save()  
{  
    CustomerRepository.Save();  
}  
}  
  
Public class CustomerRepository  
{  
    Public bool Save(dattype data)  
{  
              //Sql Connection object and Save data in Sql server   
}  
}  

The preceding code is tightly coupled because the current repository deals with the SQL server. So if the requirement is to use an Oracle server then there is modification required for the Customer class.

So to avoid that, make the customer class depend on abstraction. The following is an image of a class diagram where the customer depends on abstraction and supports both SQL and Oracle servers.



Public Class Customer   
{  
    CustomerRepository CustomerRepository;  
    Public Customer   
    {  
        CustomerRepository = new CustomerRpository();  
    }  
  
    Public bool Save()   
    {  
        CustomerRepository.Save();  
    }  
}  
  
Public class CustomerRepository   
{  
    Public bool Save(dattype data)   
    {  
        //Sql Connection object and Save data in Sql server     
    }  
} 

So in the preceding code the customer class depends on ICustomerRepository abstraction, in other words an interface. Another thing is here the customer class receives a dependency via consumption of the customer class or using a dependency container.

Note: Here is an example of the class but the same goes for the modules designed in software because dependency inversion is about providing a set of abstraction policies on which the details depend and the policy that provides flexibility in the software system.

Disadvantages

Application modules become tightly coupled, that means:
  1. The testability of the module becomes difficult.
  2. Parallel development of the module becomes difficult.
  3. Many changes are required when there is modification in the module and when there are changes in the module it depends on. 
Read more Dependency Injection talks about the disadvantages and advantages of using dependency inversion.

Note: Dependency Injection is not the same as Dependency Inversion because Dependency Inversion is about defining an abstraction policy for the software module whereas Dependency Injection is a set of patterns to supply dependency.

Saturday, January 18, 2014

Dependency Injection Part - 1

In this Article I am going to discuss about "Dependency injection" on which I am working and exploring. In this article I am going to discuss about what is dependency injection and why there is need of this software design pattern.

Dependency injection

To understand dependency injection better way, let’s consider below code,

Public class client
{
     Public static void main()
     {
        NeedDependencyClass a = new NeedDependencyClass();
     }
}

public class NeedDependencyClass
{
  Private readonly DependencyClass _b;
  public NeedDependencyClass ()
  {
     _b = new DependencyClass();
  }
  public void Test()
  {
     _b.Test();
  }
}

public class DependencyClass
{
  public void Test()
  {
    // code for text method
  }
}
In above code class client creates NeedDependencyClass and use it, then class NeedDependencyClass consume service of class DependencyClass to perform task i.e. class NeedDependencyClass is depend on class DependencyClass to perform task. This kind of the code is hardcoded dependency.
Image above shows the representation of creation and use of the objects.


Problem with code is
  1. Class NeedDependencyClass itself responsible for creating its own dependency.
  2. Code is tightly coupled, because dependency cannot be replaceable.
  3. Code also violate “Open Closed” rule of SOLID principal which says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". Because do changes in the Test method I need to modify DependencyClass.
  4. Testing of Class NeedDependencyClass becomes difficult as I cannot replace Dependency class DependencyClass with other dependency.
Dependency injection is software development pattern which introduced to resolve above problems.

Definition of this pattern is: Remove hard coded dependency and make it possible to replace at run-time or compile time.

In following section I am going to describe how problem listed above get resolved with the Dependency injection pattern.

Solution

1)Make client i.e. first class in dependency graph which consume service to create all dependent object
Resolution to the first problem of code above, pass the responsibility of supplying all required dependency to the first in dependency graph i.e. client class which is first class of the dependency graph.

So the code will change like this

Public class client
{
     Public static void main()
     {
        NeedDependencyClass a = new NeedDependencyClass(new DependencyClass());
      }
}

public class NeedDependencyClass
{
  Private readonly DependencyClass _b;
  public NeedDependencyClass(DependencyClass b)
  {
     _b = b;
  }
  public void Test()
  {
     _b.Test();
  }
}

public class DependencyClass
{
  public void Test()
  {
    // code for text method
  }
}
Image below shows object creation only done by client class object and others class down the line use supplied defendant object.



2)Removes tight coupling between object i.e allow to define loose coupling
To understand the second problem better way, let’s consider with the real life scenario of Computer or laptop.
 

 

As you can see in the above image we have the port for each device external device to which I can associate external device and do our work.

But problem with this is I cannot attach my keybord on printer port and vice versa, same problem occurs with the other devices. So this is like tight coupling that I cannot change my external device on the give interface i.e. on which I am depends.

Solution to this is USB port.

If I have USB port than I can easily attach any device to my machine and perform my task.



What is tight coupling between classes? (In programming)

Let start with simple example:

public class NeedDependencyClass
{
  Private readonly DependencyClass _b;
  public NeedDependencyClass(DependencyClass b)
  {
     _b = b;
  }
  public void Test()
  {
     _b.Test();
  }
}

public class DependencyClass
{
  public void Test()
  {
    // code for text method
  }
}

Now as you see in above code class NeedDependencyClass utilized class DependencyClass, this means that class NeedDependencyClass is depend on class DependencyClass. This type of dependency is tight dependency between class NeedDependencyClass and class DependencyClass. Because class DependencyClass is passed as parameter to class NeedDependencyClass and class NeedDependencyClass utilizing method of class DependencyClass. Now if the why it called as tightly coupled. If code is like this to create

NeedDependencyClass a = new NeedDependencyClass(new DependencyClass()); 

now if I created class DependencyClass1 like as follows public

class DependencyClass1 { 
      public void Test() 
      { //code for text method } 
}

and I want to pass DependencyClass1 instead of DependencyClass in class and want to call test method

NeedDependencyClass a = new NeedDependencyClass(new DependencyClass1()); 

This will give compiler error because I am trying to pass DependencyClass1 object as parameter. So this means Class NeedDependencyClass cannot accept any another class than Class DependencyClass.

Solution to this problem is define and interface as below which get implemented by classes

Interface IDependencyClass
{
   Void Test();
}

Class DependencyClass : IDependencyClass
{
 ……
}
Class DependencyClass1 : IDependencyClass
{
 ……
}

So the code become like this

public class NeedDependencyClass
{
  Private readonly IDependencyClass _b;
  public NeedDependencyClass(IDependencyClass b)
  {
     _b = b;
  }
  public void Test()
  {
     _b.Test();
  }
}

And this code will work both the class DependencyClass and DependencyClass1

Image below shows DependencyClass object creation only done by client class object and others class down the line use supplied dependent object. And class NeedDependencyClass is depends on the interface IDependencyClass, which can be implemented and replicable by any new class DependencyClass.

3) Make your class depend on Abstraction
Now there is requirement like only authenticated user of the application can run Test method in the application, than developer of the class need to modify the Test method like this.

public class DependencyClass : IDependencyClass
{
  public void Test()
  {
    using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, 
        "YOURDOMAIN"))
 {
      bool isValid = pc.ValidateCredentials("myuser", 
       "mypassword");
               if(isValid)
         Console.Writeln(“Testing method for the data”);
               
 } 
  }
}

That’s violate SOLID principle “Open Close” which says "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification".

So to avoid it same as make use of the abstraction i.e. create interface as which already done for to resolve tight coupling, so class extension can be done easily.

Below is how to extend the code that doesn’t break “Open Close” principle.

Class DependencyClass : IDependencyClass
{
 public void Test()
  {
    Console.Writeln(“Testing method for the data”);
  }
}

Class SecureDependencyClass : IDependencyClass
{
  IDependencyClass _b; 
  public SecureDependencyClass(IDependencyClass b)
  {
    _b = b;
  }
  public void Test()
  {
    using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, 
        "YOURDOMAIN"))
 {
      bool isValid = pc.ValidateCredentials("myuser", 
       "mypassword");
               if(isValid)
         this._b.Test();   
               
 } 
  }
}

As you see in above code new class is created with the name SecureDependencyClass. This class extends the functionality of the previous class and also not breaks “Open Close” principle.

This is done by injecting exiting class DependencyClass in the new class SecureDependencyClass i.e that is also example of Dependency injection. So SecureDependencyClass consume dependency DependencyClass.

And which change consumer client code like as below

Public class client
{
     Public static void main()
     {
        IDependencyClass dependency = new SecureDependencyClass(new 
       DependencyClass());
        NeedDependencyClass a = new NeedDependencyClass(dependency);
      }
}

public class NeedDependencyClass
{
  Private readonly IDependencyClass _b;
  public NeedDependencyClass(IDependencyClass b)
  {
     _b = b;
  }
  public void Test()
  {
     _b.Test();
  }
}

Image below shows SecureDependencyClass object creation only done by client class object and others class down the line use supplied dependent object. And class NeedDependencyClass is depends on the interface IDependencyClass, which can be implemented and replicable by any new class SecureDependencyClass.


This also shows the NeedDependencyClass is not dependent on specific class but on the Abstraction.

4) Make class Testable
Now once the second step class NeedDependencyClass easily becomes testable. Because problem with original code is hardcode dependency that is not replaceable.

Example , following is the final code

public class NeedDependencyClass
{
  Private readonly IB _b;
  public NeedDependencyClass(IB b)
  {
     _b = b;
  }
  public int Test()
  {
     var c=_b.Test();
     return c*10;
  }
}

public class DependencyClass :IDependencyClass
{
  public void Test()
  {
    // code for getting value form database
    using(SqlConnection c = new SqlConnection(connectionstring))
    {
     c.open(); 
        SqlDataReader myReader = null;
SqlCommand    myCommand = new SqlCommand("select count(*) from table", c);
        return (Int32) cmd.ExecuteScalar();
  }
}

As per the code Test method of the class DependencyClass does connection with sql server and return value.

But for testing of the class NeedDependencyClass there is no need to perform expensive database connection. So we replace class DependencyClass with the TestDependencyClass class like as below.

public class NeedDependencyClass
{
  Private readonly IDependencyClass _b;
  public NeedDependencyClass(IDependencyClass b)
  {
     _b = b;
  }
  public int Test()
  {
     var c=_b.Test();
     return c*10;
  }
}

public class TestDependencyClass :IDependencyClass
{
  public void Test()
  {
     return 10;
  }
}

Public class TestClient
{
     Public static void main()
     {
NeedDependencyClass a = new NeedDependencyClass(new TestDependencyClass());
      }
}

Conclusion

So Dependency injection is one of important design pattern which allows developing maintainable code which also satisfies SOLID principals. DI not only helpful in above this problem but we can also achieve below, Other thing can be achievable by DI is
  1. Parallel programming of application
  2. Late Binding