Skip to content

Interface Segregation Principle ​

Don’t force clients to depend on methods they don’t use.

Intent ​

Prefer many small interfaces over one fat interface. A print-only device should only know about printing.

Problem ​

Machine demands print, fax, and scan. An old printer can only print. It still must stub fax and raise on scan — a lie forced by the base type.

Solution ​

Split into Printer, Scanner, and Fax. Implement only what you need. A multi-function device composes the small roles.

Structure ​

PieceRole
Machine / OldFashionedPrinterFat interface (violation)
Printer / Scanner / FaxSegregated interfaces
*Impl classesFocused implementations
MultiFunctionDeviceImplDelegates to _printer, _scanner, _fax

Compare code ​

Violation — fat Machine

python
class OldFashionedPrinter(Machine):
    def print(self, document): ...
    def fax(self, document): pass  # forced
    def scan(self, document):
        raise NotImplementedError  # forced

Compliant — small interfaces + compose

python
class PrinterImpl(Printer):
    def print(self, document):
        print(document)

class MultiFunctionDeviceImpl(MultiFunctionDevice):
    def __init__(self, printer, scanner, fax):
        self._printer = printer
        self._scanner = scanner
        self._fax = fax

    def fax(self, document):
        self._fax.fax(document)

Walkthrough ​

Quick check ​

Which design follows ISP?

Run locally ​

bash
uv run isp

Expected:

text
Hello, world!
Scanning Hello, world!
Faxing Hello, world!

Source: main.py · tutorial README

Takeaway ​

  • Fat interfaces force stub methods and lies
  • Split by client need
  • Compose multi-capability types from small roles