Skip to content
LLD Learn/SOLID Principles
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

Interface Segregation Principle

5 min read

You'll learn to

  • -Split a fat interface into smaller, role-specific ones so implementers never depend on methods they do not use
  • -Balance ISP against over-fragmenting interfaces into too many tiny pieces

The Interface Segregation Principle (ISP) states that no client should be forced to depend on methods it does not use. In practice: a single "fat" interface that bundles unrelated capabilities forces every implementer to either implement methods that make no sense for it, or throw exceptions from them - which is the interface-level cousin of the Liskov Substitution violations from the previous chapter.

The Classic Fat-Interface Trap

A Worker interface with work() and eat() methods looks reasonable for a HumanWorker, but forces a RobotWorker to implement eat() with an empty body or an exception - RobotWorker has been forced to depend on a method it genuinely has no use for. The fix is splitting Worker into Workable (work()) and Eatable (eat()), so HumanWorker implements both and RobotWorker implements only Workable, with no dead or exception-throwing method anywhere.

Splitting a fat interface by actual capability
# Before: RobotWorker is forced to implement eat(), which makes no sense
class Worker(ABC):
    @abstractmethod
    def work(self) -> None: ...
    @abstractmethod
    def eat(self) -> None: ...

# After: capabilities are separate, implemented only where they apply
class Workable(ABC):
    @abstractmethod
    def work(self) -> None: ...

class Eatable(ABC):
    @abstractmethod
    def eat(self) -> None: ...

class HumanWorker(Workable, Eatable): ...
class RobotWorker(Workable): ...  # never forced to implement eat()

Do Not Fragment Past the Point of Usefulness

ISP has the same overcorrection risk as SRP: splitting an interface into one method per interface "just in case" produces a maze of tiny types that adds ceremony without adding clarity. The right granularity groups methods that are always needed together by the same kind of client - Readable with read() and close() makes sense as one interface if every reader always needs both; splitting those two apart would be fragmentation without a real client ever needing just one.

A fast interview test for ISP: pick each concrete implementer of an interface and ask "does this class have a real, working body for every method here?" Any method it fakes or throws from is a segregation candidate.

Interview Signal

A Printer interface has print(), scan(), and fax(). A SimpleInkjetPrinter can only print. How do you handle this?

Weak Answer

"Have SimpleInkjetPrinter implement Printer and just throw NotSupportedException from scan() and fax()."

Strong Answer

"That's exactly the ISP violation - SimpleInkjetPrinter would be forced to depend on methods it can't honor. I'd split Printer into separate Printable, Scannable, and Faxable interfaces, and have SimpleInkjetPrinter implement only Printable. A MultiFunctionPrinter can implement all three without any class ever faking a capability it doesn't have."

Check Yourself1 / 3

What does the Interface Segregation Principle state?

ScaleDojo Logo
Initializing ScaleDojo