BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Programming Concepts

Dependency Inversion Principle

The sixth and final article in the SOLID Principles series describes the Dependency Inversion Principle (DIP). The DIP states that high level modules should not depend upon low level modules and that abstractions should not depend upon details.

Refactored Code

To refactor the code to comply with the DIP we must remove the direct dependency that the TransferManager has on the BankAccount class. We could introduce a new interface for accounts that contains the methods we require to add and remove funds. However, in this case I have introduced two new interfaces. ITransferSource includes a method that allows funds to be removed from an account. ITransferDestination includes the method for adding funds to an account. The separation of the two interfaces complies with the Interface Segregation Principle (ISP) and allows for the inclusion of accounts that accept payments but cannot be the source of funds.

The BankAccount class is modified so that it implements the new interfaces. TransferManager is modified so that the Source property expects an ITransferSource object and the destination is an ITransferDestination. No direct dependencies on concrete classes now exist. Instead, both the high level class and the low level class depend upon the two abstractions.

The earlier UML diagram can now be redrawn:

Dependency Inversion Principle applied

The refactored code is as follows:

public interface ITransferSource
{
    void RemoveFunds(decimal value);
}


public interface ITransferDestination
{
    void AddFunds(decimal value);
}


public class BankAccount : ITransferSource, ITransferDestination
{
    public string AccountNumber { get; set; }

    public decimal Balance { get; set; }

    public void AddFunds(decimal value)
    {
        Balance += value;
    }

    public void RemoveFunds(decimal value)
    {
        Balance -= value;
    }
}


public class TransferManager
{
    public ITransferSource Source { get; set; }

    public ITransferDestination Destination { get; set; }

    public decimal Value { get; set; }

    public void Transfer()
    {
        Source.RemoveFunds(Value);
        Destination.AddFunds(Value);
    }
}
22 January 2011