Single Responsibility Principle
The Single Responsibility Principle (SRP) states a class should have one reason to change — one axis of responsibility.
Introduction
The Single Responsibility Principle (SRP) states a class should have one reason to change — one axis of responsibility. In LLD interviews, SRP keeps classes explainable in one sentence: 'ParkingLot assigns spots,' not 'ParkingLot handles SQL, email, and PDF tickets.'
Violations create God classes that interviewers probe with 'what happens when we add SMS receipts?' If the answer requires editing a 400-line class, SRP failed.
SRP is the most cited SOLID principle in OOD rounds — master it before the others.
Understanding the topic
Key concepts
- One class → one stakeholder or concern that drives change.
- Separate persistence, validation, notification, and domain logic.
- Service layer orchestrates; entities hold domain state.
- SRP at method level: methods do one thing well.
- Splitting too fine is also a smell — balance cohesion.
- Package-level SRP: module owns one bounded context slice.
flowchart LRSRP --> OCP --> LSP --> ISP --> DIP
Step-by-step explanation
- List reasons the class might change (schema, tax rules, UI format).
- If more than one independent reason, extract classes.
- Introduce collaborator interfaces injected via constructor.
- Keep entity focused on domain invariants.
- Move cross-cutting concerns to aspects or dedicated services.
- Re-check after each new requirement in interview extensions.
Informative example
Split reporting from order processing — each class one reason to change:
public final class OrderProcessor {private final OrderRepository repository;private final InventoryService inventory;public OrderProcessor(OrderRepository repository, InventoryService inventory) {this.repository = repository;this.inventory = inventory;}public Order process(NewOrder cmd) {inventory.reserve(cmd.items());Order order = Order.create(cmd);repository.save(order);return order;}}public final class OrderReporter {private final OrderRepository repository;public OrderReporter(OrderRepository repository) {this.repository = repository;}public String dailySummary(LocalDate day) {return repository.findByDay(day).stream().map(Order::totalDisplay).collect(Collectors.joining("\n"));}}
Reporting format changes touch OrderReporter only; fulfillment rules touch OrderProcessor only.
Real-world use
Real-world applications
- Refactoring fat controllers in interview follow-ups.
- Designing service boundaries in microservice modules.
- Explaining class splits during code review.
Best practices
- Describe each class in one sentence without 'and'.
- Extract when a method name needs 'And' in the middle.
- Co-locate tightly coupled operations in same class.
- Use package structure to reflect responsibilities.
- SRP enables unit tests with fewer mocks.
Common mistakes
- One class per database table with no behavior (anemic + fragmented).
- Confusing SRP with 'only one method'.
- Splitting entities until relationships are untraceable.
- Utility class dumping ground violating SRP globally.
Advanced interview questions
Q1BeginnerWhat is SRP?
Q2BeginnerWhy does SRP matter in interviews?
Q3IntermediateHow is SRP different from 'do one thing'?
Q4IntermediateGive an SRP violation example.
Q5AdvancedApply SRP to a monolithic ATM class.
Summary
One class, one reason to change. Separate domain, persistence, and presentation concerns. Orchestrators coordinate focused collaborators. SRP improves testability and interview clarity. Avoid God classes and vague utilities.