What is the Single Responsibility Principle?
At its core, the Single Responsibility Principle (SRP) advocates for a singular focus for each module, class, or function within a software system. In essence, it states that every component should have one and only one reason to change.
The Single Responsibility Principle states that a class/function should have only one reason to change. In other words, each class/function should have a single responsibility (purpose).
Explanation
Imagine you have a bunch of toys in your room. Each toy has its own specific job. For example, a ball is for bouncing, a toy car is for rolling, and a stuffed animal is for hugging. Similarly, in programming, SRP says that each part of your code (like a class or a function) should have only one specific job to do. It's like each part of your code is a toy with its own special purpose.
Example: A Calculator
Think about a calculator. Its job is to perform calculations, like adding numbers together or multiplying them. Now, imaging if the calculator also handled displaying colorful graphics or playing music. That would be confusing, right? SRP tells us that the calculator should stick to its main job of doing math. Other tasks, like displaying graphics or playing music, should be done by something else.
Why is SRP Important?
- Easy to Understand: Just like you know what each toy in your room is for, with SRP, it's clear what each part of your code does. This makes it easier for you and other people to understand the code.
- Easy to Fix: If one part of your code isn't working right, it's easier to find and fix the problem when each part of the code has a single job. You don't have to worry about other things getting in the way.
- Easy to Change: Let's say you want to change how one part of your code works. With SRP, you can focus on just that part without accidentally messing up other parts. It's like changing one toy without affecting the others.
- Makes Code Neater: When each part of your code does one thing well, your overall code becomes more organized and cleaner. It's like having a tidy room where everything has its place.
Key Points of SRP
- One Responsibility: A class should only be responsible for one piece of functionality or behavior. It should have one well-defined responsibility.
- Cohesion: A class with a single responsibility will have a high degree of cohesion because all methods in the class will be related to that responsibility.
- Low Coupling: By keeping the class focused on a single responsibility, it can interact with other classes through well-defined interfaces, minimizing dependencies.
Real-World Example of SRP
Example 1: Incorrect Approach
Imagine you're building an application for Employee Management. Here's a class that violates the Single Responsibility Principle:
class Employee {
public:
string name;
string position;
void saveToDatabase() {
// Code to save the employee details to a database
}
void generatePaySlip() {
// Code to generate the employee's pay slip
}
};
In this case, the Employee
class has two reasons to change:
- Changes in how employee data is saved (Database operations).
- Changes in how pay slips are generated (Payroll logic).
By combining both responsibilities into the same class, any change related to payroll would require modifications to the Employee
class, as would changes related to database operations. This makes the class harder to maintain.
Example 2: Refactored Approach (Following SRP)
We can refactor the design to adhere to SRP by splitting the responsibilities into separate classes:
// Class responsible for saving employee data to the database
class EmployeeRepository {
public:
void saveToDatabase(Employee& employee) {
// Code to save employee details to a database
}
};
// Class responsible for generating pay slips
class PaySlipGenerator {
public:
void generatePaySlip(Employee& employee) {
// Code to generate pay slip
}
};
// Employee class now only stores employee information
class Employee {
public:
string name;
string position;
};
Now, the Employee
class is only responsible for storing employee data, while the EmployeeRepository
handles saving the data, and the PaySlipGenerator
handles generating pay slips. This design adheres to the Single Responsibility Principle.