SOLID Principles – Dependency Inversion Principle [DIP]

SOLID stands for Single Responsibility Principle [SRP], Open Closed Principle [OCP], Liskov Substitution Principle [LSP], Interface Segregation Principle [ISP] and Dependency Inversion Principle [DIP].

In this article I will explain Dependency Inversion Principle [DIP]. This principle states that

  • High level modules should not depend on low level modules rather both should depend on abstraction.
  • Abstraction should not depend on details; rather detail should depend on abstraction.

Lets understand it through example.

Copy Class Definition

Copy class dependent on KeyboardReader and PrinterWritter class.

The Copy class defined in above class diagram reads user input from KeyboardReader class and sends it to Printer using PrinterWritter class. As the diagram suggests high level component Copy class depends on two low level components KeyboardReader, PrinterWritter. Since Copy class directly uses KeyboardReader and PrinterWritter classes, so if we want to redirect the output to some other output device or file system for e.g. FileStream we have to change Copy class implementation, which is not ideal.

namespace DIP_Bad
{
    using System;

    public class Program
    {
        static void Main(string[] args)
        {
            Copy badCopy = new Copy();
            badCopy.DoWork();
            Console.ReadLine();
        }
    }

    public class KeyboardReader
    {
        public string Read()
        {
            return Console.ReadLine();
        }
    }

    public class PrinterWritter
    {
        public void Write(string output)
        {
            Console.WriteLine(output);
        }
    }

    public class Copy
    {
        private KeyboardReader reader;
        private PrinterWritter writter;

        public void DoWork()
        {
            this.reader = new KeyboardReader();
            this.writter = new PrinterWritter();
            this.writter.Write(this.reader.Read());
        }
    }
}

DIP helps us to solve this issue by defining an abstraction layer between high level module and low level modules. Below diagram shows this abstraction layer with the help of Interfaces IReader and IWritter. Note that, Copy class depends on abstraction i.e. IReader and IWritter interfaces. KeyboardReader implements IReader interface and PrinterWritter and FileWritter implements IWritter interface. So this design adheres to both the points mentioned in DIP.

Copy class dependent on interfaces

Copy class dependent on interfaces

Below code example demonstrates DIP implementation

namespace DIP_Good
{
    using System;

    public interface IReader
    {
        string Read();
    }

    public class KeyboardReader : IReader
    {
        public string Read()
        {
            return Console.ReadLine();
        }
    }

    public interface IWriter
    {
        void Write(string output);
    }

    public class PrinterWriter : IWriter
    {
        public void Write(string output)
        {
            Console.WriteLine(string.Format("Writing to printer {0}", output));
        }
    }

    public class FileWriter : IWriter
    {
        public void Write(string output)
        {
            Console.WriteLine(string.Format("Writing to file {0}", output));
        }
    }


    public class Copy
    {
        private IReader reader;
        private IWriter writer;

        public Copy(IReader reader, IWriter writer)
        {
            this.reader = reader;
            this.writer = writer;
        }

        public void DoWork()
        {
            this.writer.Write(this.reader.Read());
        }
    }

    public class Program
    {
        public static void Main()
        {
            // Send output to Printer
            IReader r = new KeyboardReader();
            IWriter pw = new PrinterWriter();
            Copy cp = new Copy(r, pw);
            cp.DoWork();

            // Send output to FileStream now 
            IWriter fw = new FileWriter();
            Copy cpf = new Copy(r, fw);
            cpf.DoWork();

            Console.ReadLine();
        }
    }
}

I hope this article was helpful to you.

Thanks.

Download Source Code

5 Comments

  1. Himanshu Pandey · March 9, 2015 Reply

    Hi Prasad Honrao,

    You have write the very good articles on SOLID principle and is very helpful for me to build the more software design logic.

    Regards
    Himanshu Pandey

  2. Ofer Yuval · April 11, 2015 Reply

    Hello Prasad Honrao,
    I found this article helpful.
    It helped me understand the DEPENDENCY INVERSION PRINCIPLE, its implementation and the overhead
    involved.
    I read with interest the other articles about SOLID principles.
    Thank you !
    Ofer

  3. Sona · June 14, 2015 Reply

    Thanks for article.

  4. Chakri · November 24, 2015 Reply

    Hello Prasad,

    I have gone through couple of your articles on SOLID principles. They are good and easily reachable to novice programmer also.
    Your examples are also simple and elegant.

    Keep the good work !!!

    Thanks

Leave a Reply