What is Single Responsibility Principle?
- Single Responsibility Principle is one of the five principles of SOLID acronym.
- Single Responsibility Principle (SRP) says that “a class should have only one reason to change”
- Everyone likes a “Jack of all trades, master of none”
- “Is it really a good in software design”? Will it be good for a single class, to provide all the required functionalities?
In ‘Principles of Object Oriented Design (OOD)’ Robert C Martin, define ‘responsibility‘ to be ‘a reason to change’.
- If a class has more than one ‘responsibility’, that means the class has more than ‘one reason to change’.
- If a class has more than one functionality it should be fixed by moving the additional responsibilities to new classes.
- When we start adopting Single Responsibility principle, It will prevents the unwanted changes to our class.
Example: Employee class to analyze Single Responsible Principle
package org.learn.srp;
//enum representing department of employee
enum Department_t {
HR, FINANCE, DISPLAY, CONSUMER_ELECTRONICS
}
// Dummy class ..It will contain data members/methods to interact with database
class DatabaseHandler {
}
public class Employee {
String name;
int empId;
int salary;
Department_t department;
public Employee(String name, int emp_id, Department_t department) {
// Update the data member;
}
int updateSalary(int new_slary) {
// Update salary of employee
// ...............
// ........
return 0;
}
void change_department(Department_t department) {
// Change department of employee
// ...code goes here
// ......
}
int update_employee_database(DatabaseHandler db) {
// Update salary of employee in database
// ...............
// ........
return 0;
}
};
//enum representing department of employee
typedef enum Department { HR,
FINANCE,
DISPLAY,
CONSUMER_ELECTRONICS } Department_t;
// Dummy class ..It will contain data members/methods of database
class DatabaseHandler;
class Employee {
public:
Employee(std::string name, int emp_id, Department_t department)
{
// Update the data member;
}
int update_salary(int new_slary)
{
// Update salary of employee
// ...............
// ........
return 0;
}
void change_department(Department_t department)
{
// Change department of employee
// ...code goes here
// ......
}
int update_employee_database(DatabaseHandler& db)
{
// Update salary of employee in database
// ...............
// ........
return 0;
}
private:
std::string m_name;
int m_emp_id;
int m_salary;
};
Analyze Employee class (Single Responsibility Principle):
- It is prudent for the Employee class to provide a member function to update the salary and department of the Employee object.
- They share the same responsibility of maintaining correct state of the Employee object.
- But what about the ‘update_employee_database(DatabaseHandler& db) ?
- The method update_employee_database updates the database, which holds the Employee records.
The million-dollar question: Should update_employee_database method be part of the Employee class? Going by SLP, answer should be NO. Responsibility of updating the database should not be part of the Employee class. A change in update logic of employee table in database, could introduce a change in the Employee class, which is completely undesirable. Updating the database records should be handled by a separate class.
Developers unknowingly add more responsibility to a class, when there is bug fix or when they try to add a new functionality to a software.
- One problem often noted, with practicing SRP is increasingly, large number of smaller classes. Because it is at the discretion of developer, how developer defines a responsibility. Moreover, having large number of classes is always better than having one huge class, which is catering multiple functionalities.
- Another counter argument for SRP is having bigger class with more than one responsibility will result in more cohesive class. That is a decision, that the designer/developer has to take, anticipating how frequently the functionality can change.
- Also there are debates on why having a single responsibility in a class is better than having two or three cohesive responsibilities. That is something which should be left to the judgment of the designer/devloper.
The idea or aim behind SRP is to prevent unwanted and unrelated changes to a class. If we are achieving it then we are on right track to meet the objective of SRP.
