C# Solid Principles - Dependency Inversion Principle

Design Patterns Çağrı ŞİŞMAN 18.7.2017

Dependency inversion is the last of the SOLID principles. So we can say that Dependency Inversion principle is about cleaned structure for designing sofware applications. 

In OOP we can define classes,interfaces and many objects which are dependent to each other. Some classes can use other classes to implement different operations.We are talking about dependency and is this dependency so important? Let's have a look to below example code.

 

public class S3DataLoader
{


	public void Load()
	{

		//Load data to S3 bucket.
	}     

}

 

 

public class ServiceProcessor
{

       private S3DataLoader _s3DataLoader;

       public ServiceProcessor(S3DataLoader s3DataLoader)
       {
            _s3DataLoader=s3DataLoader;
       }     

       public void DoProcess()
       {

           _s3DataLoader.LoadData();

       }


}

 

We have two classes to implement our operations.

S3DataLoader: Designed to load data to Amazon S3 bucket.
ServiceProcessor: Uses s3DataLoader class and does some operations.

We can say easily that ServiceProcessor is responsible to manage processes and is also dependent to S3DataLoader class. If we want to compare these two classes, ServiceProcessor is a high-level class and S3DataLoader is low-level class. Everything looks like ok but if we decide to change data loading strategy, what will we have to do? 


When we decide to load the data to the database, we have to add a new class and change ServiceProcessor class caused by dependency. So we can say that the design is too bad.  At this point we can look at the rules of Dependency Inversion principle. 

-High-level modules should not depend on low-level modules. Both should depend on abstractions.
-Abstractions should not depend upon details. Details should depend upon abstractions.

Dependencies should handled by defining abstractions using interfaces. For above example S3DataLoader and SqlDataLoader classes are doing same operations by different methods.

 

public interface IDataLoader
{

        void LoadData();
}

 

 

public class S3DataLoader:IDataLoader
{

       public void LoadData()
       {

           //S3 Data Loading Process


       }
}

 

public class SqlDataLoader:IDataLoader
{


        public void LoadData()
        {


            //Load data to sql
        }

}

 

public class ServiceProcessor
{

       private IDataLoader _dataLoader;

       public ServiceProcessor(IDataLoader dataLoader)
       {
            _dataLoader=dataLoader;
       }     

       public void DoProcess()
       {

           _dataLoader.LoadData();

       }


}

 

Now ServiceProcessor doesn't need low level class.High level class module uses interface as an abstract layer. If we want to chance loading strategy, ServiceProcessor doesn't need to change. 


Etiketler: C#