Single Responsibility Principle (SRP)
Concept
The Single Responsibility Principle (SRP) states that a class, module, or function should have one, and only one, reason to change. It means that every component should focus on a single piece of functionality.
If your class is handling user authentication, parsing JSON, and sending emails all at once, it is violating SRP.
The Problem (Violation)
Consider a User class that handles both business logic and database operations:
class User {
constructor(public name: string, public email: string) {}
// Responsibility 1: Business Logic
changeEmail(newEmail: string) {
if (!newEmail.includes("@")) throw new Error("Invalid email");
this.email = newEmail;
}
// Responsibility 2: Database Operations
saveToDatabase() {
db.query(`INSERT INTO users (name, email) VALUES ('${this.name}', '${this.email}')`);
}
// Responsibility 3: Formatting
generateReport() {
return `User Report: ${this.name} - ${this.email}`;
}
}
If we switch from MySQL to MongoDB, we have to modify the User class. If we want to change the report format from Text to PDF, we have to modify the User class. The class has multiple reasons to change.
The Solution
Split the responsibilities into separate, highly-cohesive classes:
// Responsibility: Business Logic and State
class User {
constructor(public name: string, public email: string) {}
changeEmail(newEmail: string) {
if (!newEmail.includes("@")) throw new Error("Invalid email");
this.email = newEmail;
}
}
// Responsibility: Database Operations
class UserRepository {
save(user: User) {
db.query(`INSERT INTO users (name, email) VALUES ('${user.name}', '${user.email}')`);
}
}
// Responsibility: Formatting
class UserReportGenerator {
generateHtml(user: User) {
return `<h1>${user.name}</h1><p>${user.email}</p>`;
}
}
Real-World Use Case
In modern web frameworks, SRP is heavily enforced via architecture. For example, in an MVC (Model-View-Controller) architecture:
- Models represent data and relationships (SRP: Data schema).
- Controllers handle HTTP routing and validation (SRP: HTTP traffic).
- Services handle complex business logic (SRP: Business rules).
- Repositories handle database queries (SRP: Data persistence).
Interview Questions
Q: How do you identify if a class is violating SRP?
A: A good rule of thumb is to describe what the class does out loud. If you use the word “and” (e.g., “This class processes payments and sends email receipts”), it is likely violating SRP. Another sign is a class with massive line counts (God Objects) or highly unrelated dependencies (e.g., a math calculation class importing a database driver).