Question 7 · Section 18

What is Interface Segregation Principle?

The Interface Segregation Principle (ISP) states: "Clients should not depend on methods they do not use.

Language versions: English Russian Ukrainian

Deep Dive (Under the Hood)

The Interface Segregation Principle (ISP) states: “Clients should not depend on methods they do not use.

Client — a class that depends on an interface (calls its methods or implements it). If an interface forces a class to implement methods it doesn’t need — ISP is violated.”

At the bytecode and JVM level, a large interface (Fat Interface) creates unnecessary dependencies in the Constant Pool of every implementing class. Constant Pool — a reference table in the .class file. Each interface method adds an entry. VTable — virtual method table. More methods = larger table = slightly more memory and slower calls. But the main problem is architectural: code “pollution” with stub methods.


Senior Insight: Role Interfaces vs Header Interfaces

1. Header Interfaces (Anti-pattern)

This is when for every class MyService an interface IMyService is created that simply copies all its public methods.

  • Problem: This is not an abstraction, it’s just duplication. When adding a method to the service, it’s added to the interface, and all its clients are forced to recompile.

2. Role Interfaces (Senior Approach)

An interface should describe the role of an object in a specific interaction, not all its capabilities.

  • One class can implement 10 small role interfaces (Serializable, Cloneable, Printable).
  • A client (e.g., printer) only requires Printable, and it doesn’t care whether the object can save to a database.

Signs of ISP Violation

  1. UnsupportedOperationException: The clearest sign. You implemented a method only because the interface forced you to, but there’s no logic for it.
  2. Empty methods: Similarly, the method simply does nothing.
  3. Fat contracts: When testing a method requires mocking 20 functions in the interface, even though the method uses only one.

Solution via Adapter Pattern

Sometimes you can’t change the “fat” interface of a third-party library. In this case, use an Adapter:

// Third-party fat interface
public interface ThirdPartyCloud {
    void upload();
    void delete();
    void list();
    void billing(); // We don't need this
}

// Our narrow interface
public interface SimpleUploader {
    void upload();
}

// Adapter complies with ISP for our application
public class CloudAdapter implements SimpleUploader {
    private final ThirdPartyCloud cloud;
    public void upload() { cloud.upload(); }
}

Performance and Highload

  • Binary Compatibility: ISP improves binary compatibility. If you add a method to a narrow Payment interface, it only affects services that actually work with payments, not the entire project.
  • Cache Locality: Fewer methods in the interface (and, accordingly, in the VTable of objects) can theoretically fit slightly better in the CPU instruction cache, but in practice this is a micro-optimization.

Edge Cases

  • Default Methods (Java 8+): Allow adding methods to interfaces without breaking implementations. However, this does not save from ISP violation. The interface still remains “fat”, it just now pollutes the client’s namespace with default methods.
  • Single Method Interfaces: One-method interfaces are a good guideline, but not a dogma. An interface with 2-3 related methods (e.g., open()/close()/isOpen()) can also be correct.

When NOT to Strictly Follow ISP

  1. Interface with 1-2 methods — no point in splitting further
  2. All implementations use all methods — splitting brings no benefit
  3. Package-internal interface — not visible externally, minimal impact

Summary for Senior

  • Interfaces belong to clients, not implementations.
  • Prefer many small interfaces over one large one.
  • Use Default Methods with caution.
  • Remember: ISP reduces coupling and simplifies testing by reducing the number of mocks.

🎯 Interview Cheat Sheet

Must know:

  • ISP: clients should not depend on methods they do not use
  • Fat Interface forces classes to implement unnecessary methods → UnsupportedOperationException and stubs
  • Role Interfaces > Header Interfaces: interface describes a role, not all class capabilities
  • Interfaces belong to clients, not implementations
  • Adapter pattern helps comply with ISP for third-party libraries
  • Default Methods (Java 8+) don’t save from ISP violation — they just pollute the namespace

Common follow-up questions:

  • Header Interface vs Role Interface? — Header copies all class methods (anti-pattern), Role describes a specific role (Printable, Serializable)
  • How does ISP simplify testing? — Fewer mocks: the tested class depends only on the methods it needs
  • Should an interface with 1-2 methods be split? — No, further splitting brings no benefit
  • How is ISP related to DIP? — Narrow interfaces are more stable abstractions that modules depend on

Red flags (DO NOT say):

  • “Every class needs its own interface” (that’s Header Interface — an anti-pattern)
  • “Default methods solve the ISP problem” (no, the interface remains fat)
  • “A 20-method interface is fine” (depends on how many methods the client uses)

Related topics:

  • [[8. What is Dependency Inversion principle]]
  • [[3. What is Open Closed principle]]
  • [[5. What is Liskov Substitution principle]]
  • [[15. How SOLID helps in code testing]]