Interface Segregation Principle
The Interface Segregation Principle (ISP) states that no client should be forced to depend on methods it does not use. When an interface grows too large, classes that implement it must provide stubs or throw exceptions for methods that are irrelevant to them. Those stubs are a design indicator: they show that the interface has more surface area than any single implementor requires.
The principle was articulated by Robert C. Martin alongside the other four SOLID principles. The underlying issue is that a wide interface couples unrelated capabilities, so a change in one capability can ripple to every class that implements the interface — including ones that never use the changed method.
The fat-interface problem
Consider a device-management system that controls office hardware. A single MultifunctionDevice
interface covers every capability a modern all-in-one machine provides: printing, scanning, and
faxing. The initial implementation is an OfficeAllInOne class that supports all three. When the
team adds a BasicDeskPrinter — a printer that can only print — the only way to satisfy the
interface is to stub the unsupported operations.
1# Bad: fat interface forces BasicDeskPrinter to implement methods it cannot support
2from abc import ABC, abstractmethod
3
4class MultifunctionDevice(ABC):
5 @abstractmethod
6 def print_document(self, doc: str) -> None: ...
7
8 @abstractmethod
9 def scan_document(self) -> str: ...
10
11 @abstractmethod
12 def fax_document(self, doc: str, number: str) -> None: ...
13
14
15class BasicDeskPrinter(MultifunctionDevice):
16 def print_document(self, doc: str) -> None:
17 print(f"Printing: {doc}")
18
19 def scan_document(self) -> str:
20 raise NotImplementedError("This printer cannot scan")
21
22 def fax_document(self, doc: str, number: str) -> None:
23 raise NotImplementedError("This printer cannot fax")
Every caller that holds a MultifunctionDevice reference must account for the possibility that
scanDocument() throws. Tests must handle stub behavior. If the fax signature changes,
BasicDeskPrinter is recompiled — even though faxing is not a capability it supports.
The fix is to break the wide interface into smaller, focused ones. Each interface covers exactly one capability. Classes implement only the interfaces that correspond to their actual capabilities.