SOLID Design Principles - Interface Segregation Principle

2020, November 29

SOLID is a set of five design principles used in object-oriented programming to make software easier to understand, flexible and maintain.

Robert C. Martin introduced the theory of SOLID in year 2000 on his paper Design Principles and Design Patterns. Later, Micheal Feathers introduced the SOLID acronym.

SOLID stands for

  • Single-responsibility Principle
  • Open-closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Following writing will discussed on one of the principles which is Interface Segregation Principle (ISP).


Table of contents


Concept

Many client-specific interfaces are better than one general-purpose interface.
-Robert C. Martin

The general idea of ISP is client should not forced to implement methods it does not use. Thus, the approach is to splits several interfaces into smaller and specific interfaces, so the client can implements the specific interfaces which related to them.

Having an interface with define methods which unrelated to each others will make the interface become a fat interface or populated interface. When implement such interface, developer also need to write implementation for unused methods resulted in dummy methods which have no values in the implementation.

Thus, the implement is rigid for a fat interface due to developer need to manage changes for all clients when making change to a single interface. Therefore, the advantages of ISP will keep a system decoupled and make refactor an implementation easier as each interface will only has methods which required by its client.


Example

Consider an example of a factory application. In a factory consists of Worker which is a human worker, Robot as robot worker. As human worker, they can work and eat. But for a robot worker, they can only work.

Bad Example

Therefore, below is the bad application for the factory application.

public interface IWorker {
  public void eat();
  public void work();
}

IWorker.java

public class Worker implements IWorker {
  public void eat() {
    // ...eating
  }

  public void work() {
    // ...working
  }
}

Worker.java

public class Robot implements IWorker {
  public void eat() {
    // ...do nothing
  }

  public void work() {
    // ...working
  }
}

Robot.java

From the implementation, developer also need to implement eat() method for Robot class because the class implement IWorker interface. This make the method become a dummy method for Robot class, thus resulted IWorker interface become fat interface.

Good Example

Thus, IWorker interface need is split into several specific interfaces. So, IFeedable can define eat() method and IWorker only define work() method.

public interface IFeedable {
  public void eat();
}

IFeedable.java

public interface IWorker {
  public void work();
}

IWorker.java

public class Worker implements IWorker, IFeedable {
  public void eat() {
    // ...eating
  }

  public void work() {
    // ...working
  }
}

Worker.java

public class Robot implements IWorker {
  public void work() {
    // ...working
  }
}

Robot.java

Thus, by splitting work() method and eat() method in specific interfaces, each class can implement the interfaces which related to them. So, Robot class no longer need to implement eat() method.


Conclusion

In conclusion, Interface Segregation Principle enables developer to split a general-purpose interface to several specific interfaces. Later, the client can implement the interface which needed by them.

Therefore, the client no need to implement dummy method leads to system decoupled and refactor easier. Moreover, if developer need another function for a client, they can create a specific interface for the function and implement to the client.


References