I · SOLID
Interface Segregation
No client should be forced to depend on methods it doesn't use — split fat interfaces into small, role-specific ones.
✗ The problem
↓ forced to implement all
One fat interface, forced stubs
Every machine must implement all three methods — even a plain printer that can't scan or fax.
interface IMachine {
print(doc);
scan(doc);
fax(doc);
}
class OldPrinter implements IMachine {
print(doc) { /* real work */ }
scan(doc) { throw new Error('not supported'); }
fax(doc) { throw new Error('not supported'); }
}
IMachine
print · scan · fax
OldPrinter
scan() / fax() → throw
Clients depend on methods they don't use. A change to
fax()
forces recompile/retest of printers that never fax.
✓ Refactor
↑ implemented by only who needs them
Split into small role interfaces
Each class implements only the roles it actually needs.
interface Printer { print(doc); }
interface Scanner { scan(doc); }
interface Fax { fax(doc); }
class OldPrinter implements Printer { … }
class MultiFunctionDevice
implements Printer, Scanner, Fax { … }
Printer
print()
Scanner
scan()
Fax
fax()
OldPrinter
Printer
MultiFunctionDevice
Printer · Scanner · Fax
Small interfaces ← only the classes that actually need them.
No more stub methods that throw.
✓ See it live
Fat interface vs segregated
Toggle the design, then call a method on each device — watch which calls are even possible.
OldPrinter
print · scan · fax
—
MultiFunctionDevice
print · scan · fax
—
Fat mode: OldPrinter carries scan()/fax() it can't fulfil — calling them throws.
✓ Takeaway
Many small interfaces beat one fat one
- Rule: clients should depend only on the methods they actually use.
- Smell: stub methods that
throwor do nothing — a sign the interface is too fat. - Related: closely tied to SRP — an interface should have one reason to change, just like a class.
- Benefit: smaller, focused contracts are easier to implement, mock, and evolve.
Back to all topics →