Skip to main content
CodeOath
← All posts

Architecture & Patterns110 min total · 26 parts

ACID, SOLID, and Design Patterns: A Complete Software Design Reference

Part 10 of 26 · ~2 min

Interface Segregation Principle

No implementer should end up writing code for a capability that plainly doesn't apply to it. Pack unrelated abilities into one wide interface and every class that implements it is stuck between two bad options: actually build out every listed ability whether it makes sense for that class or not, or fake the ones that don't.

A sixteen-year-old signs up to volunteer at the shelter. She can check in at the kiosk and she's cleared the minors' background-check track — but she legally can't drive the shelter's van on supply runs, which the original interface assumed every volunteer could do:

// Violates ISP — a minor volunteer has no honest way to implement
// DriveShelterVan(), but the interface forces some implementation to exist.
public interface IVolunteer
{
    void CheckIn(int shiftId);
    void SubmitBackgroundCheckResult(bool passed);
    void DriveShelterVan(string route);
}

public class MinorVolunteer : IVolunteer
{
    public void CheckIn(int shiftId) { /* real implementation */ }
    public void SubmitBackgroundCheckResult(bool passed) { /* real implementation */ }
    public void DriveShelterVan(string route) => throw new NotSupportedException(); // a lie the compiler can't catch
}
// Segregated into focused interfaces — implement only what genuinely applies.
public interface ICheckInable { void CheckIn(int shiftId); }
public interface IBackgroundCheckable { void SubmitBackgroundCheckResult(bool passed); }
public interface IVanDriver { void DriveShelterVan(string route); }

public class AdultVolunteer : ICheckInable, IBackgroundCheckable, IVanDriver
{
    public void CheckIn(int shiftId) { }
    public void SubmitBackgroundCheckResult(bool passed) { }
    public void DriveShelterVan(string route) { }
}

public class MinorVolunteer : ICheckInable, IBackgroundCheckable
{
    public void CheckIn(int shiftId) { } // no forced implementation of a capability that doesn't apply
    public void SubmitBackgroundCheckResult(bool passed) { }
}

That thrown NotSupportedException is exactly the smell worth flagging when reviewing someone else's pull request: an override whose entire body amounts to refusing the method makes a statement about the interface, not about whoever wrote the implementing class. The right response is splitting the interface, never asking the class to somehow try harder.