Interface Segregation Principle
debt(d7/e5/b5/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no' even though phpstan and psalm are listed — these tools can flag structural heuristics like interfaces with 10+ methods or classes throwing UnsupportedOperationException on stubs, but they cannot reliably detect ISP violations as a matter of design intent without manual review. Code review is the primary mechanism for catching fat interfaces and no-op stubs.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says to split fat interfaces into small focused ones, but this is not a one-liner — it requires identifying natural capability boundaries, creating new interface files, updating all implementing classes, and updating all type hints referencing the old interface. The common_mistakes note that adding methods to existing interfaces 'breaks all implementors,' confirming multi-file impact.
Closest to 'persistent productivity tax' (b5). ISP violations apply across web, cli, and queue-worker contexts per applies_to. Fat interfaces force every implementor to stub unused methods, and every new feature added to the fat interface ripples to all implementors. This creates a sustained productivity drag across multiple work streams but does not quite reach the level of shaping the entire system's architecture (b7).
Closest to 'notable trap' (t5). The misconception field explicitly states that developers believe 'one large interface is simpler to manage than many small ones,' which is a well-documented gotcha that most OOP developers eventually learn. The confusion between ISP and SRP (noted in common_mistakes) adds a secondary cognitive trap. This is a documented pitfall but not one that contradicts how similar concepts work in other languages — it's an intermediate-level design principle trap.
Also Known As
TL;DR
Explanation
The I in SOLID, ISP states that a class implementing an interface should not be forced to implement methods it doesn't use. Fat interfaces that bundle unrelated methods force implementors to provide stub implementations for irrelevant methods. The solution is to split large interfaces into smaller, cohesive ones and have classes implement only what they need. This complements the Dependency Inversion Principle — depend on the narrowest interface needed for the task.
Common Misconception
Why It Matters
Common Mistakes
- One large repository interface with 20 methods — every implementation must stub 15 unused ones.
- Adding new methods to an existing interface instead of extending it — breaks all implementors.
- Not splitting interfaces at natural capability boundaries — Readable, Writable, Listable rather than FileRepository.
- Confusing ISP with SRP — ISP is about interface design, SRP is about class responsibility.
Code Examples
interface Worker {
public function work(): void;
public function eat(): void; // robots don't eat!
public function sleep(): void; // robots don't sleep!
}
class RobotWorker implements Worker {
public function eat(): void { throw new \Exception('Robots do not eat'); }
public function sleep(): void { throw new \Exception('Robots do not sleep'); }
}
interface Workable { public function work(): void; }
interface Feedable { public function eat(): void; }
interface Restable { public function sleep(): void; }
class HumanWorker implements Workable, Feedable, Restable { ... }
class RobotWorker implements Workable { ... }