Interface Segregation Principle

1 min read
On trails:CSSOLIDstep 5/6

Clients should not be forced to depend on methods they do not use. So it’s better to have many small, client-specific interfaces than one large, general-purpose (“fat”) interface.

In C#

Take a single IWorker interface with the methods Work() and Eat(). If a RobotWorker class implements IWorker, but robots don’t eat, it’s forced to provide an empty or exception-throwing implementation for Eat(). Splitting it into IWorkable (with Work()) and IEatable (with Eat()) lets classes implement only what they need.

First, the violation. The fat IWorker interface forces a robot to implement Eat().

C#
// Violation of ISPpublic interface IWorker_Bad { void Work(); void Eat(); }public class HumanWorker_Bad : IWorker_Bad {    public void Work() { /*... */ }    public void Eat() { /*... */ }}public class RobotWorker_Bad : IWorker_Bad {    public void Work() { /*... */ }    public void Eat() { throw new NotSupportedException("Robots don't eat."); } // Forced implementation}

Then the version that follows ISP. The two small interfaces come first, and the robot implements only IWorkable.

C#
// Adherence to ISPpublic interface IWorkable { void Work(); }public interface IEatable { void Eat(); }public class HumanWorker_Good : IWorkable, IEatable { /*... */ }public class RobotWorker_Good : IWorkable { /*... */ } // Only implements what it needs

Where it matters

ISP leads to more cohesive interfaces and reduces coupling. Classes only depend on the functionality they actually use, which makes the system more modular, easier to understand, and less prone to breaking changes when an interface is modified.


Sources