It is the first and one of the most important principles of object orientation (OOP).
Its objective is to understand classes and their responsibilities within the system. It is one of the easiest to understand and apply, and is based on the following premise:
Important
A class should have one, and only one, reason to change.
Let's look at the class below:
public class GenerateInvoice{
public void ValidateCustomerData(){ ... }
public void ApplyTax(decimal TotalValue){ ... }
public void SaveReceipt(decimal FinalValue) { ... }
public void SendNotifcationByEmail() { ... }
}
Here we have a fictitious class, which despite compiling and running, has a series of responsibilities that are not inherent to it:
- Validate customer data;
- Apply tax;
- Save receipt;
- Send receipt by e-mail;
Note that the class has four responsibilities, that is, four reasons for being modified.
This breach of responsibilities can generate a series of problems.
If one of the methods is changed in a way that generates a bug, the entire structure of the class may be compromised, and the system may stop issuing invoices.
When we work with SRP, we have the feeling that we are creating many classes for little use, but when the system's functionalities grow, we can realize that expansion is nothing more than creating new classes in the right places and connecting them cohesively.
So what should be done to make this class cohesive?
Simple, separate the class responsibilities making them unique:
public class Customer{
ValidateData();
}
public class Tax{
Apply(decimal TotalValue);
}
public class Receipt{
Save(decimal FinalValue);
}
public class Notification{
SendByEmail();
}
Let's see the gains we had by applying SRP to the class?
- Ease of code maintenance and evolution;
- Clean and easy-to-understand code;
- Ease of test development;
- Reduced coupling;
- Reduced complexity;
- Class cohesion;
Seeing the benefits we had with a simple refactoring, we cannot deny the need to apply SRP to our applications.
I hope I helped!