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

    Single Responsibility in Practice

    Single Responsibility sounds obvious and is the most violated principle in practice.

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

    Introduction

    Single Responsibility sounds obvious and is the most violated principle in practice. A useful definition: one reason to change driven by one stakeholder. Pricing changes when the pricing team asks; persistence when DBAs ask; notifications when marketing asks. If one class serves three stakeholders, three teams fight over one file.

    The story

    A retail platform's Order class had 4,000 lines, edited 200 times in a year by twelve engineers across four teams. Every release had merge conflicts. After Extract Class along stakeholder lines — Pricing, Fulfilment, Notification, Audit — conflicts fell to near zero.

    The business problem

    SRP violations scale painfully with team size:

    • Merge conflict clusters in god-files touched by every team.
    • Coupled tests — exercising pricing requires spinning up email mocks.
    • Ownership blur — no team can safely refactor "shared" modules.
    • Release coupling — one team's change blocks another's deploy.

    The problem teams faced

    Symptoms of multi-stakeholder modules:

    • One class edited by product, platform, and compliance in the same sprint.
    • Tests require unrelated setup to test one behavior.
    • Documentation impossible — module "does everything."
    • Fear of touching the file — workarounds multiply around it.

    Understanding the topic

    SRP test: finish this sentence with one role — "This module changes when ___ asks."

    • Cohesion — methods operate on the same data for the same reason.
    • Stakeholder — team or role requesting changes.
    • Refactor moves — Extract Class, Move Method, module split.

    Internal architecture

    Stakeholder → module mapping:

    text
    Pricing team → PricingService / PricingStrategy
    Ops team → FulfilmentService
    Marketing → NotificationService
    Compliance → AuditLogger
    Orchestrator → OrderService (thin — coordinates only)

    Visual explanation

    Three diagrams for SRP in practice:

    God class → stakeholder split
    Order (4000 LOC)
    4 teams edit
    Pricing
    Pricing team
    Fulfilment
    Ops team
    Notify
    Marketing
    Split where stakeholders disagree — not where methods look different.
    SRP diagnostic
    Who asks?
    List stakeholders
    One answer?
    SRP OK
    Many answers?
    Split candidate
    Extract Class
    By cluster
    If two stakeholders never change independently, keep them together.
    SRP at every level
    Module
    Service boundary
    Class
    Type boundary
    Function
    Does one thing
    Review all
    Not just classes
    SRP applies to functions and modules — not only classes.

    Informative example

    Before / after — order handling split by stakeholder:

    ts
    // ❌ SRP violation — three stakeholders, one class
    class Order {
    calculateTotal() { /* pricing team changes */ }
    save() { /* DBA changes */ }
    sendConfirmationEmail() { /* marketing changes */ }
    }
    // ✅ One stakeholder per class
    class OrderPricing { total(cart: Cart): Money { /* ... */ } }
    class OrderRepository { save(order: Order): Promise<void> { /* ... */ } }
    class OrderNotifier { confirm(order: Order): Promise<void> { /* ... */ } }
    class PlaceOrderHandler {
    constructor(
    private pricing: OrderPricing,
    private repo: OrderRepository,
    private notifier: OrderNotifier,
    ) {}
    async execute(cart: Cart) {
    const order = { total: this.pricing.total(cart) };
    await this.repo.save(order);
    await this.notifier.confirm(order);
    }
    }

    Execution workflow

    1SRP refactor workflow
    1 / 5

    List stakeholders

    Who requests changes to this file? By team/role.

    Git shortlog shows who touches it.

    Real-world use

    Spring stereotypes encode SRP: @Repository, @Service, @Controller. DDD bounded contexts are SRP at architecture scale. Microservices often emerge when SRP violations between teams become unbearable — but in-process SRP split is cheaper when teams share a repo.

    Production case study

    The 4,000-line Order refactor (above):

    • Before: 200 edits/year, 12 engineers, merge conflicts every release.
    • After: four focused modules, team-owned boundaries, near-zero conflicts.
    • Metric: p95 PR review time on order flow dropped 45%.
    • Lesson: SRP payoff multiplies when team size exceeds five.

    Trade-offs

    • Cohesive modules are easier to test, own, and document.
    • Risk of Lazy Class over-splitting — one-method classes that add noise.
    • Naming "the one responsibility" is harder than it sounds.

    Decision framework

    • Split when 3+ stakeholders edit the same module regularly.
    • Split when files dominate merge conflict reports.
    • Keep together when one stakeholder owns all behavior and data.
    • Skip on stable 30-line utilities.

    Best practices

    • Use git shortlog + blame to prove multi-stakeholder pain before splitting.
    • Thin orchestrators coordinate; fat logic lives in focused services.
    • Apply SRP to functions — if a function parses AND persists, split it.

    Anti-patterns to avoid

    • One class per method "for SRP" — Lazy Class smell.
    • Splitting by technical layer only (all SQL in one god Repository).

    Common mistakes

    • Extracting without tests — SRP refactor becomes incident generator.
    • Splitting classes that always change together — artificial boundaries.

    Debugging tips

    • Merge conflict heatmap → top files → stakeholder audit.
    • Test setup lines count → coupled responsibilities signal.

    Optimization strategies

    • Schedule SRP refactors before adding headcount to a god module.

    Common misconceptions

    • SRP ≠ one method per class. Cohesive related methods serving one stakeholder belong together.

    Advanced interview questions

    Interview Prep

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

    3 questions
    1IntermediateQuestionHow do you define 'one responsibility'?+

    Answer

    One stakeholder — one reason to change. Who asks for edits? If multiple roles, split.

    Follow-up

    Class you'd refuse to split?
    2AdvancedQuestionCost of SRP violations?+

    Answer

    Merge conflicts, coupled tests, fear of change. Quantify with git churn and conflict counts.

    Follow-up

    How measure conflicts?
    3AdvancedQuestionCan SRP go too far?+

    Answer

    Yes — Lazy Class. Group methods that change together under one stakeholder.

    Follow-up

    Example of harmful over-splitting.

    Summary

    You can diagnose SRP violations by stakeholder, split god classes with Extract Class, and avoid lazy over-splitting. Tell the 4,000-line Order story with metrics.

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