Question 1 · Section 18

What is Single Responsibility Principle and How to Apply It

In simpler terms, each class should deal with one specific thing. This doesn't mean "do one thing" — it means a class should be responsible for one specific part of the system's...

Language versions: English Russian Ukrainian

🟢 Junior Level

Single Responsibility Principle (SRP) is one of the five SOLID principles, which states: “A class should have only one reason to change.

Reason to change — a requirement from a specific stakeholder or system. For example: the accounting department asks you to change the salary formula (one reason), while IT asks to change the database driver (another reason). If two different departments can ask you to change the same class — SRP is violated.”**.

In simpler terms, each class should deal with one specific thing. This doesn’t mean “do one thing” — it means a class should be responsible for one specific part of the system’s functionality.

Simple analogy: Think of a restaurant. The chef cooks food, the waiter serves customers, the cashier takes payments. If one person does everything — chaos ensues.

SRP violation example:

// Bad: class does too much
public class Employee {
    public void calculateSalary() { /* salary calculation */ }
    public void saveToDatabase() { /* save to DB */ }
    public void generateReport() { /* report generation */ }
    public void sendEmail() { /* send email */ }
}

SRP-compliant example:

// Good: each responsibility in its own class
public class Employee {
    // Only employee data
    private String name;
    private BigDecimal salary;
}

public class SalaryCalculator {
    public BigDecimal calculate(Employee emp) { /* calculation */ }
}

public class EmployeeRepository {
    public void save(Employee emp) { /* save to DB */ }
}

public class EmailService {
    public void sendNotification(Employee emp) { /* send email */ }
}

When to use:

  • As a guideline — follow SRP in most cases. Exceptions: prototypes, MVPs, stable utilities, scripts of 50-100 lines.
  • When creating new classes
  • When refactoring existing code

🟡 Middle Level

How It Works

SRP is closely related to the concepts of:

  • Cohesion — how much the methods of a class work toward one purpose. Higher is better.
  • Coupling — how much a class depends on other classes. Less is better.

How to Detect SRP Violation

Signs of violation:

  1. “And” Rule: if you describe a class as “it does X AND Y AND Z” — SRP is violated
  2. Different stakeholders: if different departments can demand changes in one class
  3. Huge import list: if a class imports too many dependencies
  4. Difficult testing: if testing one method requires mocking 5+ dependencies

Practical Application

// SRP violation: OrderProcessor does everything
public class OrderProcessor {
    public void process(Order order) {
        validateOrder(order);         // Validation
        saveOrder(order);             // DB operations
        sendConfirmation(order);      // Sending notifications
        logToAnalytics(order);        // Logging
        updateInventory(order);       // Inventory update
    }
}

// SRP-compliant: delegating responsibilities
public class OrderProcessor {
    private final OrderValidator validator;
    private final OrderRepository repository;
    private final NotificationService notifier;
    private final AnalyticsLogger logger;
    private final InventoryService inventory;

    public void process(Order order) {
        validator.validate(order);
        repository.save(order);
        notifier.sendConfirmation(order);
        logger.log(order);
        inventory.update(order);
    }
}

Common Mistakes

  1. Mistake: Creating Utils, Helper, Manager classes Solution: Break them into specialized classes by domain area

  2. Mistake: Spring @Service with 20+ autowired dependencies Solution: Split into several services by business capability

  3. Mistake: Excessive decomposition (100 classes of 5 lines) Solution: Find balance — group by features, not by technical layers

When NOT to Strictly Follow SRP

  1. Prototypes and MVPs — speed is more important than architecture
  2. Scripts of 50-100 lines — splitting into 5 classes adds complexity
  3. Stable utilities — if the code doesn’t change, SRP is not needed

🔴 Senior Level

Internal Implementation and Architecture

SRP is a change management principle, not just “one class — one function”. Robert Martin’s (Uncle Bob) original definition states:

“A module should have only one reason to change”

At the Senior level, it’s important to understand: SRP applies not only to classes, but also to modules, services, and even microservices.

Cohesion Levels

A Senior developer should distinguish types of cohesion:

Cohesion Type Description Example
Functional (best) All parts of the class are needed for one function BCryptPasswordEncoder
Sequential Output of one method is input for another OrderPipeline
Communicational Methods work with the same data UserService with user fields
Procedural Methods execute in a certain order TransactionManager
Temporal Methods execute at the same time StartupInitializer
Utility Weak cohesion, random grouping CommonUtils
Coincidental (worst) Parts ended up together by accident Helper class ❌

Architectural Trade-offs

Strict SRP compliance:

  • ✅ Pros: Easy testing, low coupling, high cohesion, minimum merge conflicts
  • ❌ Cons: Large number of classes, navigation complexity, risk of “atomic dust”

Moderate SRP compliance:

  • ✅ Pros: Balance between readability and flexibility
  • ❌ Cons: Requires mature judgment, risk of gradual degradation

Edge Cases

  1. Class Explosion Problem: When SRP is overused, the system turns into thousands of tiny classes
    • Solution: Group by business capabilities (Package-by-Feature), not by technical layers
  2. Merge Conflicts in large teams: One “popular” class is edited by 10+ developers
    • Solution: Separate responsibilities by domain areas
  3. Cognitive Load: Huge classes (God Objects) are impossible to keep in mind
    • Solution: Limit class size (200-300 lines as a guideline)

Performance

  • Memory footprint: More classes → more metadata in Metaspace. In practice, this is negligible for the JVM (a few KB per class)
  • Method dispatch: Delegation adds method calls. The JIT compiler usually performs inlining, reducing overhead to zero
  • Startup time: A large number of small classes may slightly slow down startup (metadata loading)

Production Experience

Real production scenario:

In a large e-commerce project, there was an OrderService with 3000+ lines of code and 25 dependencies. Any change led to regression bugs. The team spent 3 sprints on refactoring:

  1. Extracted PaymentProcessor, InventoryChecker, NotificationService
  2. Created OrderOrchestrator for coordination
  3. Covered each component with independent tests

Result: Deployment bugs dropped by 60%, code review time was halved.

Monitoring and Diagnostics

How to detect SRP violation in code:

  1. Code metrics:
    • Lines of code > 300
    • Number of methods > 10
    • Cyclomatic complexity > 15
    • Number of dependencies > 7
  2. Tools:
    • SonarQube (cohesion metrics)
    • Checkstyle (class size)
    • ArchUnit (architectural tests)
  3. Code Review signs:
    • Different reviewers for different parts of the class
    • Frequent Git conflicts
    • Difficulty writing unit tests

Best Practices for Highload

  • SRP in microservices: One microservice — one business goal (SRP analogy at the system level)
  • Feature Toggles: If one feature requires changes in 5+ services — perhaps service boundaries are drawn incorrectly
  • Domain-Driven Design: Aggregate Root should have one responsibility within its Aggregate

Relationship with Other Principles

  • SRP → OCP: When a class has one responsibility, it’s easier to extend without modification
  • SRP → LSP: Small classes with a single purpose are easier to inherit correctly
  • SRP → ISP: Interface segregation naturally follows from responsibility separation
  • SRP → DIP: Delegating dependencies leads to dependency inversion

Summary for Senior

  • SRP is about change management, not about the number of lines
  • Strive for Functional Cohesion, avoid Coincidental Cohesion
  • SRP reduces system fragility: changing email logic shouldn’t break price calculation
  • Use ArchUnit for automatic verification of architectural boundaries
  • Remember balance: don’t turn code into “atomic dust”
  • SRP is an investment in code maintainability for years to come

🎯 Interview Cheat Sheet

Must know:

  • SRP: a class should have only one reason to change
  • Reason to change = requirement from a specific stakeholder
  • High cohesion is a natural result of following SRP
  • SRP violation leads to God Objects, fragility, and merge conflicts
  • SRP applies not only to classes, but also to modules, services, microservices
  • Avoid Utils, Helper, Manager classes — break them by domain areas
  • Spring @Service with 20+ autowired dependencies is a clear SRP violation sign
  • SRP reduces system fragility: changing one part doesn’t break another

Common follow-up questions:

  • How to detect SRP violation? — LCOM > 1.0, >300 lines, >10 methods, >7 dependencies, complex tests with 5+ mocks
  • When can SRP be violated? — Prototypes/MVPs, scripts up to 100 lines, stable utilities
  • What is Atomic Dust? — Excessive decomposition, when the system turns into thousands of tiny classes
  • How is SRP related to other SOLID principles? — SRP makes code testable (DIP), extensible (OCP), inheritable (LSP)

Red flags (DO NOT say):

  • “SRP means a class should have only one method” (no — one responsibility, not one action)
  • “I always follow SRP without exceptions” (no — prototypes and scripts don’t need it)
  • “The more classes — the better” (no — balance between cohesion and file count)

Related topics:

  • [[2. Give an example of Single Responsibility principle violation]]
  • [[13. How is Single Responsibility principle related to cohesion]]
  • [[14. What happens if a class has multiple reasons to change]]
  • [[18. How to refactor God Object]]
  • [[21. How to determine if a class has a single responsibility]]