Bird
Raised Fist0
Interview Prepoop-design-patternseasyAmazonGoogleMicrosoftFlipkartRazorpayCREDSwiggy

Single Responsibility Principle - One Class, One Reason to Change

Choose your preparation mode3 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
🎯
Single Responsibility Principle - One Class, One Reason to Change
easyOOPAmazonGoogleMicrosoft

Imagine a library where each book covers only one topic thoroughly, so if you want to update information about that topic, you only need to revise that one book, not the entire library.

💡 Beginners often confuse 'responsibility' with 'functionality' or 'methods count', leading them to group unrelated tasks in one class simply because they seem related at a surface level.
📋
Interview Question

Explain the Single Responsibility Principle (SRP) in object-oriented design. What does it mean for a class to have a single responsibility, and why is it important? How does SRP improve code maintainability and flexibility?

Definition of responsibility in SRP contextReason to change as the guiding factor for class designImpact of SRP on cohesion and coupling
💡
Scenario & Trace
ScenarioA class handles both user authentication and logging user activities.
Initially, the class authenticates users and logs their login times. Later, a requirement changes the logging format. Because authentication and logging are in the same class, changing logging affects authentication code, increasing risk and complexity.
ScenarioSeparating payment processing and invoice generation into two classes.
PaymentProcessor class handles payment transactions, while InvoiceGenerator class creates invoices. Changes in invoice format do not affect payment logic, and vice versa, making the system easier to maintain and extend.
  • What if a class seems to have multiple responsibilities but they share the same reason to change?
  • How to handle utility/helper classes that provide multiple unrelated functions?
  • What happens if splitting responsibilities leads to excessive fragmentation and many tiny classes?
⚠️
Common Mistakes
Confusing 'responsibility' with 'number of methods or functions'

Interviewer thinks candidate lacks understanding of SRP's core idea.

Explain that responsibility means a reason to change, not just method count.

Believing SRP means one method per class

Interviewer doubts candidate's grasp of practical design.

Clarify that a class can have many methods as long as they serve one responsibility.

Ignoring that multiple responsibilities can share the same reason to change

Interviewer sees candidate as rigid and unable to reason about design trade-offs.

Emphasize that SRP is about reasons to change, so related responsibilities with one reason can coexist.

Thinking SRP applies only to classes, not modules or functions

Interviewer questions candidate's broader understanding of SRP.

Mention SRP is a design principle applicable at multiple levels, including modules and functions.

🧠
Basic Definition - What It Is
💡 This level ensures you can clearly state the principle and its core idea without confusion.

Intuition

A class should have only one reason to change, meaning it should focus on a single responsibility.

Explanation

The Single Responsibility Principle states that every class should have one, and only one, reason to change. This means a class should encapsulate a single part of the functionality provided by the software, ensuring high cohesion within the class. When a class has multiple responsibilities, changes in one area can affect unrelated parts, increasing the risk of bugs and making maintenance harder.

Memory Hook

💡 Think of a class like a specialist doctor: they focus on one specialty rather than trying to treat every illness.

Interview Questions

What does 'one reason to change' mean in SRP?
  • A reason to change corresponds to a responsibility or a stakeholder's concern.
  • If a class has multiple reasons to change, it violates SRP.
Depth Level
Interview Time30 seconds
Depthbasic

Covers the fundamental definition and why it matters at a high level.

Interview Target: Minimum floor - never go below this

Knowing only this lets you pass initial screening but lacks depth for on-site interviews.

🧠
Mechanism Depth - How It Works
💡 This level is expected in product companies and shows you understand the internal rationale and practical application.

Intuition

SRP reduces coupling and increases cohesion by ensuring each class addresses a single concern, making the system easier to maintain and extend.

Explanation

The Single Responsibility Principle works by identifying distinct responsibilities or reasons to change within a system and assigning each to a separate class. This separation ensures that changes in one responsibility do not ripple through unrelated code, reducing the chance of bugs and simplifying testing. It also improves cohesion, as each class focuses on a well-defined task. For example, separating data persistence from business logic means changes in database schema affect only the persistence class, not the business logic. SRP also facilitates parallel development and clearer code ownership.

Memory Hook

💡 Imagine a factory assembly line where each worker has a single task; if one task changes, only that worker needs retraining, not the entire line.

Interview Questions

How does SRP affect coupling and cohesion?
  • SRP increases cohesion by grouping related functionality in one class.
  • SRP reduces coupling by minimizing dependencies between classes.
  • This leads to easier maintenance and fewer side effects when changing code.
What if two responsibilities share the same reason to change?
  • They can be in the same class since the reason to change is singular.
  • SRP focuses on reasons to change, not just counting methods.
Depth Level
Interview Time2-3 minutes
Depthintermediate

Demonstrates understanding of how SRP improves design quality and maintainability.

Interview Target: Target level for FAANG on-sites

Mastering this level distinguishes you from most candidates.

📊
Explanation Depth Levels
💡 Choose depth based on interview stage and role; deeper levels impress on-site interviewers.
LevelInterview TimeSuitable ForRisk
Basic Definition30sScreening callToo shallow for on-site interviews
Mechanism Depth2-3 minutesOn-site interviews at FAANG and product companiesRequires good understanding; skipping may lose points
💼
Interview Strategy
💡 Use this guide to structure your explanation clearly and confidently before interviews.

How to Present

Start with a clear definition of SRP.Give a simple real-world analogy or example.Explain how SRP reduces coupling and increases cohesion.Discuss common edge cases and trade-offs.

Time Allocation

Definition: 30s → Example: 1min → Mechanism: 2min → Edge cases: 30s. Total ~4min

What the Interviewer Tests

Interviewer checks if you understand the principle's rationale, can identify responsibilities, and appreciate its impact on maintainability.

Common Follow-ups

  • What if a class has multiple methods but only one reason to change? → It's still SRP compliant.
  • Can SRP lead to too many small classes? → Yes, balance is needed to avoid over-fragmentation.
💡 These follow-ups test your ability to apply SRP pragmatically, not just theoretically.
🔍
Pattern Recognition

When to Use

Asked during OOP design, SOLID principles, or code maintainability discussions.

Signature Phrases

'Explain the Single Responsibility Principle''What does it mean for a class to have one reason to change?''Compare classes with multiple responsibilities vs single responsibility'

NOT This Pattern When

Similar Problems

Practice

(1/5)
1. When a client calls a method on a Proxy object that controls access to a resource-intensive service, what is the typical sequence of events that occurs internally?
easy
A. Proxy performs access control, then lazily initializes the real service if needed, and finally forwards the call
B. Proxy immediately forwards the call to the real service without any checks
C. Proxy modifies the request parameters before forwarding to the real service
D. Proxy creates a simplified interface hiding the complexity of the real service

Solution

  1. Step 1: Understand Proxy's role

    Proxy controls access and may delay creation of the real service (lazy initialization).
  2. Step 2: Trace the call flow

    Client calls Proxy -> Proxy checks access -> Proxy creates real service if not already created -> Proxy forwards call -> Real service executes.
  3. Step 3: Eliminate incorrect options

    B is incorrect because Proxy usually adds control logic before forwarding. C is incorrect as Proxy typically does not modify parameters (that's Decorator or Adapter). D describes Facade, not Proxy.
  4. Final Answer:

    Option A -> Option A
Hint: Proxy = gatekeeper + lazy loader
Common Mistakes:
  • Assuming Proxy always forwards calls immediately without checks
  • Confusing Proxy with Facade's simplification role
  • Thinking Proxy modifies request parameters
2. Trace the sequence of events when a client requests a service via Dependency Injection (DI) in an IoC container. Which step correctly follows the previous?
easy
A. Client creates the service instance directly, then passes it to the IoC container.
B. Client requests the service from the IoC container, which then creates and injects dependencies into the client.
C. Service creates the client instance and injects itself into the client.
D. IoC container instantiates the service and injects it into the client before the client uses it.

Solution

  1. Step 1: Understand DI and IoC flow

    In Dependency Injection via IoC, the client requests a service from the container, which manages creation and injection.
  2. Step 2: Analyze options

    Client requests the service from the IoC container, which then creates and injects dependencies into the client. correctly describes the client requesting the service and the container creating and injecting dependencies. Client creates the service instance directly, then passes it to the IoC container. reverses roles incorrectly. IoC container instantiates the service and injects it into the client before the client uses it. suggests container injects before client requests, which is inaccurate. Service creates the client instance and injects itself into the client. incorrectly states the service creates the client.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    IoC container controls creation; client depends on container to provide dependencies.
Hint: In DI, client asks container; container creates and injects dependencies.
Common Mistakes:
  • Thinking client creates service instances directly
  • Assuming container injects dependencies before client requests
  • Confusing who controls object creation
3. In which scenario would you rely on method overloading rather than method overriding to achieve polymorphism?
easy
A. When you want to dynamically bind method calls using a virtual table (vtable)
B. When you want to provide multiple behaviors for the same method name based on different parameter types or counts within the same class
C. When you want to change the behavior of a method at runtime depending on the object's actual type
D. When you want a subclass to provide a specific implementation of a method declared in its superclass

Solution

  1. Step 1: Understand method overloading

    Method overloading occurs within the same class and involves multiple methods with the same name but different parameter lists, resolved at compile time.
  2. Step 2: Contrast with overriding

    Method overriding involves a subclass redefining a method from its superclass, resolved at runtime via dynamic dispatch.
  3. Step 3: Analyze options

    When you want to provide multiple behaviors for the same method name based on different parameter types or counts within the same class correctly describes overloading's use case. Options A, B, and C describe overriding or runtime polymorphism concepts.
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Overloading is about compile-time resolution based on parameters, not runtime behavior changes.
Hint: Overloading = same method name, different parameters, compile-time binding
Common Mistakes:
  • Confusing overloading with overriding
  • Thinking overloading involves runtime polymorphism
  • Believing vtable is used for overloading
4. You have an object with nested mutable fields, and you need to create a new object instance such that changes to the nested fields in the new object do not affect the original. Which approach best guarantees this behavior?
easy
A. Manually copy only the top-level fields, sharing nested references to save memory
B. Use a greedy algorithm to selectively copy fields based on usage frequency
C. Serialize the object to JSON and deserialize it back to create a new instance
D. Recursively copy all nested objects to create independent duplicates

Solution

  1. Step 1: Understand the problem requirement

    The goal is to create a new object where nested mutable fields are independent, so changes in the copy do not affect the original.
  2. Step 2: Evaluate approaches

    Manual shallow copy (A) shares nested references, causing side effects. Greedy selective copying (B) is not a standard approach and risks missing nested objects. JSON serialization (D) can lose methods and fail on special objects. Recursive deep copy (C) ensures all nested objects are duplicated, preserving independence.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Deep copy duplicates nested objects -> no shared references [OK]
Hint: Deep copy duplicates nested objects fully [OK]
Common Mistakes:
  • Assuming shallow copy suffices for nested mutable fields
5. What is the worst-case space complexity of the Composite pattern iterator when traversing a tree with n nodes and height h?
medium
A. O(n) because all nodes are stored in the stack at once.
B. O(1) since the iterator uses constant extra space.
C. O(log n) assuming a balanced tree reduces height.
D. O(h) because the stack stores nodes along the current path only.

Solution

  1. Step 1: Understand iterator stack usage

    The iterator stack holds nodes along the current traversal path, not all nodes simultaneously.
  2. Step 2: Relate stack size to tree height

    Maximum stack size corresponds to the height h of the tree, as children are pushed and popped during traversal.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Stack size bounded by tree height h, not total nodes n [OK]
Hint: Iterator stack size bounded by tree height, not total nodes [OK]
Common Mistakes:
  • Assuming stack holds all nodes at once
  • Confusing height with log n for unbalanced trees