PTOM: The Dependency Inversion Principle

The Dependency Inversion Principle, the last of the Uncle Bob “SOLID” object-oriented design principles, can be thought of the natural progression of the Liskov Substitution Principle, the Open Closed Principle and even the Single Responsibility Principle.  This post is the latest in the set of SOLID posts:

The Dependency Inversion Principle, or DIP, is often used interchangeably with Dependency Injection and Inversion of Control.  However, following DIP does not mean we must automatically use a IoC container like Spring.NET, Windsor or StructureMap.  IoC containers are tools to assist in applications adhering to DIP, but we can follow DIP without using IoC containers.

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.

The DIP can be a little vague, as it talks about “abstractions” but doesn’t describe what is being abstracted.  It speaks of “modules”, which don’t have much meaning in .NET unless you consider “modules” to be assemblies.  If you’re looking at Domain-Driven Design, modules mean something else entirely.

The Dependency Inversion Principle, along with the other SOLID principles, are meant to alleviate the problems of bad designs.  The typical software I run into in existing projects has code organized into classes, but it still isn’t easy to change.  I usually see big balls of mud along with a crazy spider web of dependencies where you can’t sneeze without breaking code on the other side of the planet.

Spider webs and bad design

Bad designs and bad code is bad because it’s hard to change.  Bad designs are:

  • Rigid (change affects too many parts of the system)
  • Fragile (every change breaks something unexpected)
  • Immobile (impossible to reuse)

Some people’s ideas of “bad design” would be something like seeing string concatenation instead of a StringBuilder.  While this may not be the best performing choice, string concatenation isn’t necessarily a bad design.

It’s pretty easy to spot bad designs.  These are sections of code or entire applications that you dread touching.  A typical example of rigid, fragile and immobile  (bad) code would be:

public class OrderProcessor
{
    public decimal CalculateTotal(Order order)
    {
        decimal itemTotal = order.GetItemTotal();
        decimal discountAmount = DiscountCalculator.CalculateDiscount(order);

        decimal taxAmount = 0.0M;

        if (order.Country == "US")
            taxAmount = FindTaxAmount(order);
        else if (order.Country == "UK")
            taxAmount = FindVatAmount(order);
            
        decimal total = itemTotal - discountAmount + taxAmount;

        return total;
    }

    private decimal FindVatAmount(Order order)
    {
        // find the UK value added tax somehow
        return 10.0M;
    }

    private decimal FindTaxAmount(Order order)
    {
        // find the US tax somehow
        return 10.0M;
    }
}

The OrderProcessor sets out to do something very simple: calculate the total of an Order.  To do so, it needs to know the item total of the order, any discounts applied, as well as the tax amount (which depends on the Order’s Country).

Too many responsibilities

To see why the DIP goes hand-in-hand with the Single Responsibility Principle, let’s list out the responsibilities of the OrderProcessor:

  • Knowing how to calculate the item total
  • Finding the discount calculator and finding the discount
  • Knowing what country codes mean
  • Finding the correct taxing method for each country code
  • Knowing how to calculate tax for each country (commented out for brevity’s sake)
  • Knowing how to combine all of the results into the correct final total

If a single class (or a single method in this case) answers too many questions (how, where, what, why etc.), it’s a good indication that this class has too many responsibilities.

To move towards a good design, we need to remove the external dependencies of this class to pare it down to its core responsibility: finding the order total.  Offhand, the dependencies I see are:

  • DiscountCalculator
  • Tax decisions

In the future, we might need to support more countries, which means more tax services, and more responsibilities.  To reduce the rigidity, fragility and immobility of this design, we need to move these dependencies outside of this class.

Towards a better design

When following the DIP, you notice that the Strategy pattern begins to show up in a lot of your designs.  Strategy tends to solve the “details should depend on abstractions” part of the DIP.  Factoring out the DiscountCalculator and the tax decisions, we wind up with two new interfaces:

  • IDiscountCalculator
  • ITaxStrategy

I’m not a huge fan of the “ITaxStrategy” name, but it will suffice until we find a better name from our model.

Factoring out the dependencies

To factor out the dependencies, first I’ll create a couple of interfaces that match the existing method signatures:

public interface IDiscountCalculator
{
    decimal CalculateDiscount(Order order);
}

public interface ITaxStrategy
{
    decimal FindTaxAmount(Order order);
}

Now that I have a couple of interfaces defined, I can modify the OrderProcessor to use these interfaces instead:

public class OrderProcessor
{
    private readonly IDiscountCalculator _discountCalculator;
    private readonly ITaxStrategy _taxStrategy;

    public OrderProcessor(IDiscountCalculator discountCalculator, 
                          ITaxStrategy taxStrategy)
    {
        _taxStrategy = taxStrategy;
        _discountCalculator = discountCalculator;
    }

    public decimal CalculateTotal(Order order)
    {
        decimal itemTotal = order.GetItemTotal();
        decimal discountAmount = _discountCalculator.CalculateDiscount(order);

        decimal taxAmount = _taxStrategy.FindTaxAmount(order);

        decimal total = itemTotal - discountAmount + taxAmount;

        return total;
    }
}

The CalculateTotal method looks much cleaner now, delegating the details of discounts and tax to the appropriate abstractions.  Instead of the OrderProcessor depending directly on details, it depends solely on the abstracted interfaces we created earlier.  The specifics of how to find the correct tax method is now encapsulated from the OrderProcessor, as is the hard dependency on a static method in the DiscountCalculator.

Filling out the implementations

Now that we have the interfaces defined, we need actual implementations for these dependencies.  Looking at the DiscountCalculator, which is a static class, I find that I can’t immediately change it to a non-static class.  There are many other places with references to this DiscountCalculator, and since it’s the real world, none of these other places have tests.

Instead, I can just use the Adapter pattern to adapt the interface I need for an IDiscountCalculator:

public class DiscountCalculatorAdapter : IDiscountCalculator
{
    public decimal CalculateDiscount(Order order)
    {
        return DiscountCalculator.CalculateDiscount(order);
    }
}

In applying the Adapter pattern, I just wrap the real DiscountCalculator in a different class.  The advantage of the Adapter pattern in this case is that the existing DiscountCalculator can continue to exist, but if when the mechanism for calculating discounts changes, my OrderProcessor does not need to change.

For the tax strategies, I can create two implementations for each kind of tax calculation being used today:

public class USTaxStrategy : ITaxStrategy
{
    public decimal FindTaxAmount(Order order)
    {
    }
}

public class UKTaxStrategy : ITaxStrategy
{
    public decimal FindTaxAmount(Order order)
    {
    }
}

I left the implementations out, but I basically moved the methods from the OrderProcessor into these new classes.  Neither of the original methods used any instance fields, so I could copy them straight over.

My OrderProcessor now has dependencies factored out, so its single responsibility is easily discerned from looking at the code.  Additionally, the implementations of IDiscountCalculator and ITaxStrategy can change without affecting the OrderProcessor.

Isolating the ugly stuff

For me, the DIP is all about isolating the ugly stuff.  For calculating order totals, I shouldn’t be concerned about where the discounts are or how to decide what tax strategy should be used.  We did increase the number of classes significantly, but this is what happens when we move away from a procedural mindset to a true object-oriented design.

I still have the complexity to solve of pushing the dependencies into the OrderProcessor.  Clients of the OrderProcessor now have the burden of creating the correct dependency and giving them to the OrderProcessor.  But that problem is already solved with Inversion of Control (IoC) containers like Spring.NET, Windsor, StructureMap, Unity and others.

These IoC containers let me configure the “what” when injecting dependencies, so even that decision is removed from the client.  If I didn’t want to go with an IoC container, even a simple creation method or factory class could abstract the construction of the OrderProcessor with the correct dependencies.

By adhering to the Dependency Inversion Principle, I can create designs that are clean, with clearly defined responsibilities.  With the dependencies extracted out, the implementation details of each dependency can change without affecting the original class.

And that’s my ultimate goal: code that is easy to change.  Easier to change means a lower total cost of ownership and higher maintainability.  Since we know that requirements will eventually change, it’s in our best interest to promote a design that facilitates change through the Dependency Inversion Principle.

Related Articles:

    Post Footer automatically generated by Add Post Footer Plugin for wordpress.

    About Jimmy Bogard

    I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
    This entry was posted in PTOM. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
    • BennyXNO

      I see som holes in your “Solution”.

      Your orderprocessor takes IDiscountCalculator and a ITaxStrategy as input, but this must be wrong, because of the Strategy for taxes lies in each order and you can’t use the same Strategy for both “US” and “UK” orders. Or do you want to make a new OrderProsessor for each order? This seems somewhat troublesome to me.

    • http://jimmybogard.lostechies.com Jimmy Bogard

      @Benny

      Strategy means I can swap out implementations of an algorithm. In this case, I have a “US tax strategy” and a “UK tax strategy”, each of which calculate tax very differently. But the order processor calculates total the same each time.

      I would make a new order processor for each order. Object creation is very cheap, so I’m not worried about keeping it around.

      This code came from a legacy project where the “OrderProcessor” did way more than it should have. Typically I would move the “CalculateTotal” method to a class that better encapsulates this responsibility.

    • Peter

      In the code, you do not show any usage of the namespaces. Also, I noted that you mention DDD, so I have a question about how to use layering (namespaces dependencies) when implementing a DDD repository. IMHO, the persistence layer (aka infrastructure layer) would reference the domain layer if you apply DIP. This is quite the opposite what most people think, but according to DIP, I think that is the way it should be done.
      For example, consider these dependencies, look at the “using” and the “namespaces”:

      using DomainLayer;
      namespace PersistenceLayer {
      public class CustomerRepositoryImplementedWithNHibernate: CustomerRepository {
      public Customer FindCustomerById(int id) {

      namespace DomainLayer {
      public interface CustomerRepository {
      Customer FindCustomerById(int id);
      }
      }

      namespace DomainLayer {
      public class Customer {

      namespace DomainLayer {
      public class CustomerService {
      public CustomerRepository CustomerRepository { set; get; }
      public void “someMethod()” {

      Customer customer = CustomerRepository.FindCustomerById(123);

      The fundamental question here is whether this kind of dependency should be allowed:
      PersistenceLayer.CustomerRepositoryImplementedWithNHibernate inherits e.g. depends on DomainLayer.CustomerRepository
      (the way I comprehend DIP, the answer should be yes, even tough most people would probably spontaneously think that the dependency should be inversed)

    • http://www.lostechies.com/members/bogardj/default.aspx bogardj

      @Peter

      Repositories aren’t infrastructure, they’re part of the domain. _Implementations_ of repositories are. Keep in mind the difference between implementations and abstractions, implementation can come from Kalamazoo, but no one knows about it!

    • Peter

      Quote: “Repositories aren’t infrastructure, they’re part of the domain. _Implementations_ of repositories are. ”

      Hmm, you start the sentence by saying repositories are not part of the infrastructure (without specifying whether you mean the interface) and then you finish with the word “are” without me being quite sure whether that word refers back to domain or infrastructure, so I am not sure whether you agree or not…

      Is this what you mean ?:
      Repository INTERFACES are not infrastructure.
      Repository INTERFACES are part of the domain. IMPLEMENTATIONS of repositories are part of the infrastructure.

    • http://www.lostechies.com/members/bogardj/default.aspx bogardj

      @Peter

      Yeah that’s what I meant – implementations of repositories are typically infrastructure.

      But ultimately, it doesn’t matter what projects the classes reside in, it matters what uses what. You could put it all in one project if you like (reduces compile time). Logical != physical layering.

    • Peter

      Okay, but that means that the infrastructure layer would have a logical dependency into the domain layer.
      If you use namespaces for partitioning the logical layers (and what else than namespaces could you use for that…?) then we would get this kind of dependency from a repository implementation in the infrastructure layer/namespace to the domain layer/namespace:

      namespace DomainLayer {
      public class Customer {

      public interface CustomerRepository {
      Customer FindCustomerById(int id);

      }

      }

      namespace PersistenceLayer {
      public class CustomerRepositoryImplementedWithNHibernate: DomainLayer.CustomerRepository {
      public DomainLayer.Customer FindCustomerById(int id) {

      This is a conflict with what a lot of people think, including Eric Evans as I understand, considering his statement at page 73 in DDD book about the infrastructure layer:
      “Being below the domain layer, it should have no specific knowledge of the domain it is serving”

      So, what is the appropriate conclusion here…?
      (the way I understand it, Eric does not seem to apply the Dependency Inversion Principle for repository implementations…)

    • http://www.lostechies.com/members/bogardj/default.aspx bogardj

      I think your last comment is right – not applying DIP to implementations. It ultimately comes down to how you design your repositories. Nothing in our app depends on implementations of repositories, so we can put the implementations closer to the “infrastructure” layer, where we have quite a bit of knowledge about the infrastructure we’re using.

    • Brian