Click here to Skip to main content
Click here to Skip to main content

Dependency Inversion Principle and the Dependency Injection Pattern

, 26 Nov 2012
Rate this:
Please Sign up or sign in to vote.
Dependency Inversion Principle and the Dependency Injection Pattern

Introduction 

Everyday we write lots of code which are tightly coupled and when complexity grows code will eventually deteriorate into Spaghetti Code. Which violates the Dependency inversion principle. In software design, tight coupling is often considered to be a liability in design. When one class knows explicitly about the design and implementation of another class, its raise the risk that changes to one class will break the other class.

On the other hand loosely coupled code can stay maintainable and well-designed. The benefits of using loose coupling aren’t always instantly evident, but they become visible over time, as the complexity of a code grows. Dependency Injection Pattern is nothing but the best way to enable loose coupling. In this article I will try to explain how we can use DI in our everyday practice with simple approach without DI containers.

Background

Uncle Bob "SOLID" object-oriented design principles “D” stands for Dependency Inversion Principle

The Dependency Inversion Principle states:  

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

Sometimes its not easy to maintain DIP while writing your code. Practice and experience will help you out from this. The Dependency Inversion principle (DIP) helps to loosely couple your code by ensuring that your high-level modules depend on abstractions rather than concrete implementations of lower-level modules. The Dependency Injection pattern is an application/ implementation of this principle. 

The basic idea of this article is that how we can make our code loosely coupled.

Using the code 

Let's start from the code. Many of us probably seen (or written) code like this: 

public class Email
{
    public void SendEmail()
    {
        // code
    }
}

public class Notification
{
    private Email _email;
    public Notification()
    {
        _email = new Email();
    }

    public void PromotionalNotification()
    {
        _email.SendEmail();
    }
}

Here Notification class has a dependency on Email class. In this case, the notification creates an instance of the e-mail directly inside of the notifications constructor and knows exactly what kind of email class it’s creating and consuming. It's violate DIP.

A class has dependency on some other class and knows a lot about the other classes it interacts with is said to be tightly coupled. When a class knows explicitly about the design and implementation of another class, its raise the risk that changes to one class will break the other class.

What if we want to send some other types of notifications like SMS or save into the DB? To enable this behavior we have to modify the implementation of the notification class.

To reduce dependency we have to do couple of steps. Firstly introduce an abstraction layer between these two classes. We can use interface/ abstract class to represent the abstractions between Notification and Email.

public interface IMessageService
{
    void SendMessage();
}
public class Email : IMessageService
{
    public void SendMessage()
    {
        // code
    }
}
public class Notification
{
    private IMessageService _iMessageService;

    public Notification()
    {
        _iMessageService = new Email();
    }
    public void PromotionalNotification()
    {
        _iMessageService.SendMessage();
    }
}

Here, introduced an interface IMessageService to represent the abstraction, and ensure that the Notification class only calls methods or properties on that interface.

Secondly need to move the creation of the Email class outside of the Notification. We can achieve this by DI pattern.  

DI is the act of supplying all classes that a service needs rather that leaving the responsibility to the service to obtain dependent classes. DI typically comes in three flavors:

  • Constructor Injection
  • Property Injection
  • Method Injection

Using these injections we can achieve the second step. I am applying these injections in our tightly couple code. And making our code loosely couple and maintaining DIP. 

Constructor Injection

This is the most common dependency injection. When a class requires an instance of a DEPENDENCY to work, we can supply that DEPENDENCY through the class’s constructor. Now let’s change the Notification class to support constructor injection:

public class Notification
{
    private IMessageService _iMessageService;

    public Notification(IMessageService _messageService)
    {
        this._iMessageService = _messageService;
    }
    public void PromotionalNotification()
    {
        _iMessageService.SendMessage();
    }
}

In this code, there are several benefits: the implementation of the constructor is very simple, it has reduced the number of things Notification needs to know about, any code that wants to create an instance of Notification can look at the constructor and know exactly what kinds of things are necessary to make Notification function.  So, our code is now loosely coupled and easily maintainable.

Property Injection

Property injection/ setter injection is less common dependency injection, it is best used when dependency is optional. We have to expose a writable property that allows a client to supply a different implementation of the class’s DEPENDENCY than the default. We have to change our Notification class to apply property injection:

public class Notification
{
    public IMessageService MessageService
    {
        get;
        set;
    }
    public void PromotionalNotification()
    {

        if (MessageService == null)
        {
            // some error message
        }
        else
        {
            MessageService.SendMessage();

        }
    }
}

We have removed the constructor and replaced it with a property. Now we are providing dependency via properties rather than the constructor. In the PromotionalNotifications method we have to check that it has already provided the service dependency or not by checking MessageService value.  Here, we able to made our code loosely coupled.

Method Injection 

When a DEPENDENCY can vary with each method call, you can supply it via a method parameter. Suppose our application will send Email also SMS or save notification message into DB. We can use method injection. We can write the code following way:

public class Email : IMessageService
{
    public void SendMessage()
    {
        // code for the mail send
    }
}
public class SMS : IMessageService
{
    public void SendMessage()
    {
        // code for the sms send
    }
}

public class Notification
{
    public void PromotionalNotification(IMessageService _messageService)
    {
        _messageService.SendMessage();
    }
}

Here, IMessageService has implemented in both Email class and SMS class. We can supply different types of MessageService as a parameter to the PromotionalNotification method to perform the notification accordingly.  So, here dependency is varying every method call by different parameters.

In a tightly coupled scenario like the example, we can apply any of these injection to make our code loosely coupled. It's depends on the scenario which injection we will apply. We can apply more than one in a single scenario.

Conclusion 

Surprisingly its very easy to write tightly coupled code! One of the many reason is that while introducing new/ additional features in our code. Every time we use a new keyword we introduce a tight coupling. We can minimize this by introducing constructor injection. In general developers like to use constructor injection over the other two types of injection. But of course we can mix  both of them, while constructor will be mandatory and other two will be optional. Hope this article will help you to begin DI in your every day code.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Munir Hassan
Software Developer (Senior)
Bangladesh Bangladesh
Do code for living...

Comments and Discussions

 
GeneralRe: My vote of 5 PinmemberMaksudSaifullah20-Nov-12 7:30 
GeneralMy vote of 5 PinmemberMonjurul Habib20-Nov-12 6:27 
GeneralRe: My vote of 5 PinmemberMunir Hassan20-Nov-12 7:20 
GeneralMy vote of 3 Pinmemberdojohansen20-Nov-12 5:54 
GeneralRe: My vote of 3 PinmemberMunir Hassan20-Nov-12 7:19 
GeneralMy vote of 5 PinmemberEric Lapouge20-Nov-12 5:11 
GeneralRe: My vote of 5 PinmemberMunir Hassan20-Nov-12 5:44 
GeneralMy vote of 5 PinmemberSk. Tajbir20-Nov-12 3:36 
Nice.. Thanks for sharing this. 5
GeneralRe: My vote of 5 PinmemberMunir Hassan20-Nov-12 5:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140709.1 | Last Updated 27 Nov 2012
Article Copyright 2012 by Munir Hassan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid