Design Patterns Tutorial 0/70 lessons ~6 min read Lesson 13

    Interface Segregation

    Interface Segregation splits fat interfaces so clients depend only on methods they use.

    Course progress0%
    Focus
    21 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Interface Segregation splits fat interfaces so clients depend only on methods they use. A forty-method repository forces every mock to stub forty methods when the test needs two. ISP creates role interfaces — Reader, Writer, Search — so consumers declare minimal dependencies.

    The story

    A RepositoryBase had twenty-six methods. Mocking for one read test required stubbing twenty-six methods. After ISP split into Reader, Writer, and Search, test setup time dropped 70%.

    The business problem

    Fat interfaces tax every consumer and test:

    • Mock bloat — stub methods never called.
    • Recompile ripple — unused method changes rebuild unrelated clients.
    • LSP traps — implementations throw NotSupported on irrelevant methods.
    • Hidden dependencies — consumers coupled to capabilities they don't use.

    The problem teams faced

    Signs you need ISP:

    • Interface exceeds ~5–7 methods with distinct client groups.
    • Mocks require many `jest.fn()` stubs per test.
    • Implementations throw "not supported" for interface methods.

    Understanding the topic

    Role interfaces — small, cohesive, client-specific:

    • Role — Reader, Writer, Authenticator, Searcher.
    • Implementer — one class may implement multiple roles.
    • Client — depends on role type, not fat base.

    Internal architecture

    Before / after:

    text
    Before: OrderRepository (26 methods) ← all services depend on all
    After: OrderReader ← query services
    OrderWriter ← command handlers
    OrderSearch ← admin dashboard
    PostgresOrders implements all three

    Visual explanation

    ISP in three diagrams:

    Fat interface → role split
    FatRepo (26)
    All clients
    Reader
    Query handlers
    Writer
    Commands
    Search
    Admin UI
    Split by client usage clusters — not arbitrary method count.
    ISP + CQRS lite
    Read path
    Reader interface
    Write path
    Writer interface
    Same class
    Implements both
    Clients split
    Minimal deps
    CQRS at architecture scale is ISP taken seriously.
    Mock surface shrink
    26-method mock
    70% setup waste
    ISP split
    Role interfaces
    2-method mock
    Test focuses
    Faster tests
    Team velocity
    Test pain alone often justifies ISP refactor.

    Informative example

    User service ISP:

    ts
    // ❌ Fat interface
    interface UserService {
    getById(id: string): User;
    updateProfile(u: User): void;
    resetPassword(id: string): void;
    listAll(): User[];
    delete(id: string): void;
    exportCsv(): Buffer;
    }
    // ✅ Role interfaces — clients depend on slices
    interface UserReader { getById(id: string): User; }
    interface UserWriter { updateProfile(u: User): void; resetPassword(id: string): void; }
    interface UserAdmin { listAll(): User[]; delete(id: string): void; exportCsv(): Buffer; }
    class ProfileController {
    constructor(private users: UserReader & UserWriter) {} // only what it needs
    }

    Execution workflow

    1ISP refactor
    1 / 4

    Map clients to methods

    Which service calls which methods?

    Static analysis or grep.

    Real-world use

    AWS SDK v3 redesigned around ISP — import only the commands you use. Spring Data splits read/write repositories. ISP + SRP together: roles for clients, focused classes for implementers.

    Production case study

    Twenty-six-method repository (above): test setup −70%, mock-related test failures eliminated.

    Trade-offs

    • Smaller mocks and clearer dependencies.
    • More interface files to navigate.
    • Over-splitting creates micro-interface noise.

    Decision framework

    • Split when interface >5 methods with distinct client groups.
    • Split when mock setup pain appears in tests.
    • Keep fat interface when every client truly uses every method (rare).

    Best practices

    • Name roles by client capability: Reader, Writer, Notifier.
    • One concrete class can implement many roles.
    • If implementer throws on role methods, split was wrong — revisit SRP on class.

    Anti-patterns to avoid

    • One-method interfaces for every function — noise without cohesion.
    • ISP split without updating client constructor types.

    Common mistakes

    • Class implementing twelve roles — class itself may violate SRP.

    Debugging tips

    • Count mock stubs per test — >5 unused stubs suggests ISP opportunity.

    Optimization strategies

    • CQRS read/write split when read and write paths scale differently.

    Common misconceptions

    • ISP ≠ one method per interface. Cohesive role with 3–5 related methods is fine.

    Advanced interview questions

    Interview Prep

    Practice concise answers, then expand each card for the explanation.

    2 questions
    1AdvancedQuestionISP vs CQRS?+

    Answer

    ISP splits interfaces; CQRS splits stacks/models at architecture scale. Same intent, different zoom.

    Follow-up

    When is full CQRS overkill?
    2IntermediateQuestionWhen is fat interface OK?+

    Answer

    When every consumer uses every method — rare. Test pain usually proves otherwise.

    Follow-up

    Fat interface you'd keep?

    Summary

    You can split fat interfaces into roles, shrink test mocks, and relate ISP to CQRS. Tell the twenty-six-method repository story.

    Ready to mark this lesson complete?Track your journey across the entire course.