Single-Responsibility Principle

↝ It states that a class should have one, and only one, reason to change. What do you mean by reason to change? When a class has more responsibilities, there's a chance it might have to change its behavior later on. That's why we aim to minimize the responsibility of a class as this reduces the probability of change. When a change occurs, it should be driven by a specific reason related to that responsibility. So, more responsibility means higher probability of change.

Change creates a ripple effect, potentially impacting other classes that rely on or interact with the changed class. You can prevent unintended issues if methods are logically related and serve a common purpose. That's why it's really important to ask yourself if methods are cohesive, meaning, do these methods make sense if I group them together?

It's also important to know that SRP doesn't mean a class should only contain one method. Instead, methods should be in harmony with the class’s main responsibility. Let’s create a scenario: you are tasked with creating a class that will handle users—authenticating the user, validating their information, and performing CRUD operations on the user. You might do something like this:

class User{
 authenticateUser(){
// Authenticates a user with provided credentials, such as email, username and password
 }

logoutUser(){
// Logs out a user, typically invalidating their session or token
}

validateUser(){
 // Validates a user's credentials or access rights
}

addUser(){
// Adds a new user
}

updateUser(id, updatedDetails){
// Updates an existing user's details
}

browseUser(id){
// Retrieves details of a specific user
}

deleteUser(){
 // Deletes a user from
}
}

According to the Single Responsibility Principle (SRP), this class does not meet the requirement of having only one job. However, isn't the main purpose of this class to manage users? The issue with the class above is that it has multiple responsibilities. To follow this principle, we will break down our main class’s responsibility into three separate responsibilities—authenticating the user, validating user information, and performing BREAD operation on user.

class UserAuthentication {
 auth() {
    //....
 }
}

class UserValidation {
 validate() {
    //....
 }
}

class UserManagement {
 addUser(){
 //
}

updateUser(id){
 //
}
browseUser(id){
 //
}

deleteUser(){
 //
}
}

Why does the code above satisfy the SRP? Because you have categorized them based on their responsibilities:

  • A class to validate the information.

  • A class to authenticate them at some point.

  • A class to perform BREAD (Browse, Read, Edit, Add, Delete) actions in the database.

To sum up, ensuring that your class has only one responsibility will reduce the difficulties of refactoring as your code grows. How can you achieve this? By understanding the relationships of your methods, take some time to determine if these methods make sense when grouped together or split apart. It's also important to note that your class name must always be related to its sole responsibility. The class name should provide a clear indication of what the class should do and its limitations. Thank you, and happy coding!