Support us .Net Basics C# SQL ASP.NET ADO.NET MVC Slides C# Programs Subscribe Buy DVD

Dependency Inversion Principle Introduction

Suggested Videos
Interface Segregation Principle | Text | Slides
Open Closed Principle | Text | Slides
Liskov Substitution Principle | Text | Slides

In this video we will discuss
  • Dependency Inversion Principle Introduction
  • Understand the intention of DIP usage

In the first video of SOLID Introduction we have understood that D in SOLID stands for Dependency Inversion Principle which is also known as DIP

The Dependency Inversion Principle introduced by Robert C Martin states that  
  • High-level modules should not depend on low-level modules. Both should depend on abstractions.

    AND

  • Abstractions should not depend on details. Details should depend on abstractions.

To simplify this we can state that while designing the interaction between a high-level module and a low-level one, the interaction should be thought of as an abstract interaction between them. 

Usage Intention : Before understanding the intention of usage, let’s try to understand a traditional application architecture implementation. 

During the process of the application design, lower-level components are designed to be consumed by higher-level components which enable increasingly complex systems to be built. In this Process of Composition, higher-level components depend directly upon lower-level components to achieve some task. 

This dependency upon lower-level components limits the reuse opportunities of the higher-level components and ends up in a bad design.

dependency inversion principle

From the illustrated diagram, High-level Modules depends directly on Low-level Modules and this does not follow the first point of DIP. 

Allowing the dependency causes many issues and we have discussed many of them in our first session of this tutorial. For now, we are not going to get into details of those as it’s out of scope of this session. However, we strongly recommend you to refer to the first part of this tutorial before proceeding.

dependency inversion principle c#

Now let’s take a look at button click event example from the Presentation layer that calls directly the Employee Save Method of Business logic which does some validation checks before saving the employee details to DB. 

This flow looks absolutely fine however we are coupling different layers and as said earlier, any further changes are complicated and cumbersome.

Now, Let’s see this problem with a sample code.

public class BusinessLogicLayer
{
    private readonly DataAccessLayer DAL;

    public BusinessLogicLayer()
    {
        DAL = new DataAccessLayer();
    }

    public void Save(Object details)
    {
        DAL.Save(details);
    }
}

public class DataAccessLayer
{
    public void Save(Object details)
    {
        //perform save
    }
}

Notice from the above code the BLL is directly dependent on the low level Data Access Layer and it’s hard to perform any unit tests on this code as both are coupled. Of course, we can do some amount of testing on the DAL but imagine if the DAL needs to be further extended to SQL and XML layers. If we need to that, implementation to extend it, becomes tedious and much more complicated. 

Hence based on the DIP we apply an Abstraction to decouple these layers.

In order to achieve that we introduce interface that acts as abstraction so that both are decoupled.

This decoupling is demonstrated in the representation diagram and further we can re-write our code as shown on the screen.

dependency inversion principle tutorial

If you take a look at this code based on the pictorial representation diagram we have introduced the Interface which is extended by the Data Access Layer and referred in the BLL. Hence we can say that Irepository layer acts as abstraction between these modules.

public class BusinessLogicLayer
{
    private readonly IRepositoryLayer DAL;

    public BusinessLogicLayer(IRepositoryLayer repositoryLayer)
    {
        DAL = repositoryLayer;
    }

    public void Save(Object details)
    {
        DAL.Save(details);
    }
}

public interface IRepositoryLayer
{
    void Save(Object details);
}

public class DataAccessLayer : IRepositoryLayer
{
    public void Save(Object details)
    {
        //perform save
    }
}

Adapter Design pattern can be seen as an example which is applying the dependency inversion principle.

dependency inversion principle example

The high-level class defines its own adapter interface which is the abstraction that the other high-level classes depend on. The Adaptee implementation also depends on the adapter interface abstraction.

However, we are not going in to the detail discussion of Adapter design pattern as it's out of scope of this session. 

For more details on the Adapter Design pattern, we strongly recommend you to refer to the Adapter design pattern tutorial

Various patterns such as Plugin, Service Locator, or Dependency Injection are employed to facilitate the run-time provisioning of the chosen low-level component implementation to the high-level component.

In the next video we will further discuss the implementation of DIP using Abstraction, Dependency Inversion or Inversion of Control, Service Locater, unity containers etc using some simple examples.

solid design principles c#

No comments:

Post a Comment

If you like this website, please share with your friends on facebook and Google+ and recommend us on google using the g+1 button on the top right hand corner.