SOLID Principles – Part 05 – Interface Segregation Principle

Principle

Functionality should be broken into specific interfaces rather than one all-purpose interface. This means clients are not be forced to depend upon methods that they do not use.

Scenario

To demonstrate ISP I will continue using the E-Commerce example from the previous blog. A customer has an order which includes multiple order items. Given an order we calculate the total cost and the tax due based on US state.

Before Code

We will use the code from the previous blog however; our customer is now an Internet customer as opposed to a customer that walks into a store. We need to differentiate the two.

The first thing we do is declare our Internet customer.

public interface IInternetCustomer
{
   Customer GetCustomerById(int Id);
   void Add(Customer customer);
   void Delete(int CustomerId);
   // Imagine lots more
}

public class InternetCustomer : IInternetCustomer
{
   public Customer GetCustomerById(int Id)
   {
      // dummy data
      return new Customer { Name = "Fred", Id = Id, StateCode = "WA", County = "whocares", ZipCode = "zippy" };
   }

   #region NotRequired
   public void Add(Customer customer)
   {
      throw new NotImplementedException();
   }

   public void Delete(int CustomerId)
   {
      throw new NotImplementedException();
   }
   #endregion
}

If you take a look at the interface definition, there are methods for adding, deleting and getting a customer. Our Order class only needs to get a customer however; the interface forces us to implement methods which would be required for a customer management class.

After Code

The correct way of implementing the internet customer interface is to break it up into smaller abstractions as follows.

public interface IInternetCustomerRead
{
   Customer GetCustomerById(int Id);
}

public interface IInternetCustomerWrite : IInternetCustomerRead
{
   void Add(Customer customer);
   void Delete(int CustomerId);
   // Imagine lots more
}

public class InternetCustomer : IInternetCustomerRead
{
   public Customer GetCustomerById(int Id)
   {
      // dummy data
      return new Customer { Name = "Fred", Id = Id, StateCode = "WA", County = "whocares", ZipCode = "zippy" };
   }
}

The internet customer abstraction has been broken into two:

  • IInternetCustomerRead” contains the methods for reading.
  • IInternetCustomerWrite” contains the methods for reading and writing.

Our internet customer can implement the IInternetCustomerRead interface for use in the Order class

We can run the before and after tests and it will still work fine.

Sidenote

The code so far actually still does not conform to the full SOLID principles however; in this last blog we finally correct that.