Skip to main content

🧩 The ISP Rule

“Clients should not be forced to depend on methods they don’t use.”
Imagine a Swiss Army knife 🔪 vs specialized tools:
  • Swiss Army knife: Has everything, but each tool is mediocre
  • Specialized tools: Each does one thing perfectly
ISP says: Don’t give a fish a bicycle interface! 🐟🚲
Simple Rule: Split big interfaces into small, focused ones. Classes only implement what they need!
The gym membership analogy: Imagine a gym that forces every member to sign up for swimming, weightlifting, yoga, boxing, AND rock climbing — even if you only want to lift weights. You are paying for (and contractually obligated to maintain eligibility for) services you never use. ISP says the gym should offer separate memberships: a weights pass, a swim pass, a yoga pass. You pick only what you need. In code, this means small, focused interfaces so that implementing classes are not burdened with methods that are irrelevant to them.

🚨 The Problem: Fat Interfaces

❌ BAD: One Giant Interface


✅ GOOD: Small, Focused Interfaces


🖨️ Classic Example: Printer Interfaces

❌ BAD: Multifunction Monster

✅ GOOD: Segregated Interfaces


🎮 Real Example: Game Characters


📱 Real Example: Mobile App Features


🔄 How to Apply ISP

1

Identify the fat interface

Look for interfaces with many methods that some implementations don’t need
2

Group related methods

Which methods are always used together?
3

Create focused interfaces

One interface per group of related methods
4

Update implementations

Each class implements only the interfaces it needs

🧪 Practice Exercise

This interface is too fat. Split it!

📝 Key Takeaways

Small > Big

Many small interfaces beat one big one

No Forced Methods

Classes shouldn’t implement what they don’t need

Combine as Needed

Classes can implement multiple interfaces

Client-Focused

Interfaces should fit what clients actually need

Why ISP Matters in Production

In real codebases, fat interfaces cause a subtle but painful problem: forced coupling. If UserService depends on a DataStore interface with 30 methods (read, write, delete, batch, stream, replicate…), but UserService only ever calls read() and write(), it is still coupled to all 30 methods. When someone adds a 31st method to DataStore, UserService’s tests might break even though it uses none of the new functionality. ISP prevents this — by depending on a narrow ReadWriteStore interface with just 2 methods, UserService is insulated from changes it does not care about. A senior engineer would say: “ISP is really about coupling management. The wider the interface you depend on, the more reasons your code has to change. Narrow interfaces minimize your exposure to other teams’ changes.”

Interview Insight

ISP shows up in interviews as the “what if we add a new feature?” question. When you design a system with a monolithic interface and the interviewer says “now support a device that can only do X but not Y,” your design either handles it gracefully or crumbles. If you split interfaces upfront, adding a printer-only device that does not scan is trivial: it implements Printable and ignores Scannable. If you used a fat MultiFunctionDevice interface, you are stuck with NotImplementedError. The ISP-aware design also connects to LSP — classes that implement an interface should actually support all its methods, and small interfaces make that achievable. When presenting your design, say: “I am keeping this interface narrow so implementors are not forced to support operations they cannot perform.”

🏃 Next: Dependency Inversion Principle

Let’s learn the final SOLID principle - how to depend on abstractions!

Continue to Dependency Inversion →

Learn how to make your code flexible by depending on abstractions!