The SOLID Principles in C# – Dependency Inversion

The last post in the SOLID by Example series deals with the Dependency Inversion Principle (DIP). It states that high-level classes should not depend on low-level classes. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.

For us developers S.O.L.I.D. is a five letter acronym with each letter pointing to a basic principle of good Object Oriented Design. The principle set was introduced almost twenty years ago by Robert C. Martin (Uncle Bob), a well known author, speaker and thinker on the subject. In this series we discuss each principle with some practical code examples.

By dependencies we mean all lower-level modules, used by our code, that are likely to change. For instance files and the filesystem, databases and datasets, third party libraries and components, webservices, configuration, system resources, logging… and so on. One could even argue that the .Net Framework is a lower-level dependency.

In the traditional N-tier layering structure, where we have maybe a GUI, Business Layer and Data Access Layer, we see higher level modules instantiate and call lower-level modules. This is creating a dependency from the high-level GUI through the BLL to the lower-level DAL. These dependencies make it much harder for us to change, maintain and test the system.

In this example we have a BirthdayCalculator class which has a list of birthdays and a GetTodaysBirthdays() method to retrieve todays birthday list.

Dependency Inversion Birthday Calculator V2

We new up the birthday list inside of the BirthdayCalculator constructor.

public class BirthdayCalculator
{
    private readonly List<Birthday> _birthdays;
 
    public BirthdayCalculator()
    {
        _birthdays = new List<Birthday>();
    }
 
    public List<Birthday> Birthdays
    {
        get { return _birthdays; }
    }
 
    public List<Birthday> GetTodaysBirthdays()
    {
        // Update: 2012-08-07
        // Made an enormous booboo on this piece of code before
        // Solved thanks to Dejan
        return _birthdays
            .Where(bd => bd.Date.Month == DateTime.Now.Date.Month)
            .Where(bd => bd.Date.Day == DateTime.Now.Date.Day)
            .ToList();
    }
}

The birthday list is what we call a hidden dependency. If we create an instance of the BirthdayCalculator we don’t know it has a dependency on the list of birthdays (a lower-level class). Another hidden dependency is the explicit call to the static property DateTime.Now to query for the current system time.

Let’s inverse these dependencies. We do this by placing a small interface between our modules and let them depend upon these abstractions. In this case the IList of type Birthday. We new it up outside of the BirthdayCalculator, injecting it into the object via the constructor (dependency injection). The class design now looks something like this:

public class BirthdayCalculator
{
    private readonly IList<Birthday> _birthdays;
 
    public BirthdayCalculator(IList<Birthday> birthdays)
    {
        _birthdays = birthdays;
    }
 
    public IList<Birthday> Birthdays
    {
        get { return _birthdays; }
    }
 
    public IList<Birthday> GetBirthdays(DateTime checkDate)
    {
        return _birthdays
            .Where(bd => bd.Date.Day == checkDate.Day)
            .Where(bd => bd.Date.Month == checkDate.Month)
            .ToList();
    }
}

What we have here is an independent class with a constructor clearly stating the dependency it needs to function. The DateTime.Now is gone. The CheckDate is provided whenever the GetBirthdays method is called. We can now change and test this class much easier, because the control of the dependencies lay outside of the class.

8 thoughts on “The SOLID Principles in C# – Dependency Inversion

  1. The today birthday list will not bring any data. Why?
    Because, unless every year maintenance process update year part of birthday to current year.

    Also not very good example.

    Interface for a date, how over architectural is this. Also not to mansion that you can place any date as today, and then method GetTodayBirthday loose any sense. Also what is purpose to let outside code to set _today variable trough constructor when you override it with GetNowDate in method call.

    • Hey Dejan,

      You’re right about the GetTodaysBirthdays results. :mrgreen: Should be something like this:

      return _birthdays
      	.Where(bd => bd.Date.Day == _today.Day 
      		&& bd.Date.Month == _today.Month)
      	.ToList();
      

      I’ll take a look at it tonight and correct it.

      I still think it’s a good example showing dependency inversion in a very over exaggerating manner. DateTime.Now is an evil untestable static. Please show your take on this code so I can learn from it.

      cheers

  2. What is my understanding of IOC is that you can pass interface to a class, so dependencies are being controlled from top – high level classes.

    In the case of your code, I don’t see any purpose to implement such a constructor.

    What will be if I as a user of your class put null in both input parameters?

    What maybe be a ok example is that you remove _today, and leave only IList variable so calling from let say unit test will give me a choice to set my set of birthdays.

    Cheers!

    • Hey Dejan,

      I changed the code according to your remarks and my current knowledge of the dependency inversion principle. Checking for nulls is omitted for simplicity, but you have a point.

      It is still an over exaggerated example in which I got rid of the DateTime.Now asking for a CheckDate in the GetBirtdays method. This way it is still fully testable without the overhead I posted before. Also much cleaner.

      Thanks for the pointers!

  3. Hi
    I have seen in many examples using IList than List, but what makes it different .
    No one explained clearly. Could you please explain me about why we have to go for IList?

    Thank you
    Krishna

    • If you use a List of Birthdays here, the class would depend on the actual implementation of List. This is a hard and detailed dependency. If you use an abstraction, like IList of Birthdays, you can use any class implementing this interface without breaking any code. Easier to change and open for extension.

      In practice I would rather use an IEnumerable (of type T) in this case, being the smallest interface possible to express this functionality.

  4. Pingback: Solid Principles of object oriented design : | M.katkoot

  5. Pingback: Bob van Dam | Design Patterns

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>