Single Responsibility Principle
As the name suggests, this principle states that each class should have one responsibility, one single purpose. This means that a class will do only one job, which leads us to conclude it should have only one reason to change.
We don’t want objects that know too much and have unrelated behaviour. These classes are harder to maintain. For example, if we have a class that we change a lot, and for different reasons, then this class should be broken down into more classes, each handling a single concern. Surely, if an error occurs, it will be easier to find.
Let’s consider a class that contains code that changes the text in some way. The only job of this class is manipulating text.
Example 1
public class TextManipulator {
private String text;
public TextManipulator(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void appendText(String newText) {
text = text.concat(newText);
}
public String findWordAndReplace(String word, String replacementWord) {
if (text.contains(word)) {
text = text.replace(word, replacementWord);
}
return text;
}
public String findWordAndDelete(String word) {
if (text.contains(word)) {
text = text.replace(word, " ");
}
return text;
}
public void printText() {
System.out.println(textManipulator.getText());
}
}
Although this may seem fine, it is not a good example of the SRP. Here we have two responsibilities: manipulating and printing the text.
Having a method that prints out text in this class violate the Single Responsibility Principle. For this purpose, we should create another class, which will only handle printing text:
public class TextManipulator {
private String text;
public TextManipulator(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void appendText(String newText) {
text = text.concat(newText);
}
public String findWordAndReplace(String word, String replacementWord) {
if (text.contains(word)) {
text = text.replace(word, replacementWord);
}
return text;
}
public String findWordAndDelete(String word) {
if (text.contains(word)) {
text = text.replace(word, " ");
}
return text;
}
public class TextPrinter {
TextManipulator textManipulator;
public TextPrinter(TextManipulator textManipulator) {
this.textManipulator = textManipulator;
}
public void printText() {
System.out.println(textManipulator.getText());
}
public void printOutEachWordOfText() {
System.out.println(Arrays.toString(textManipulator.getText().split(" ")));
}
public void printRangeOfCharacters(int startingIndex, int endIndex) {
System.out.println(textManipulator.getText().substring(startingIndex,endIndex));
}
}
Now, in this class, we can create methods for as many variations of printing text as we want, because that's its job.
The single responsibility principle (SRP) states that a software component (in general, a class) must have only one responsibility. The fact that the class has a sole responsibility means that it is in charge of doing just one concrete thing, and as a consequence of that, we can conclude that there must be only one reason to change it.
Advantages of the Single Responsibility Principle
- Easy to understand and maintain
- Improved usability
Easy to understand and maintain
When the class only does “one thing”, its interface usually has a smaller number of methods (and member variables) that are fairly self-explanatory. It makes the code easier to read and understand.
When there is a need to change the application behaviour, changes related to the class’s responsibility are fairly isolated. It reduces the chance of breaking other unrelated areas of the software. It makes the code easier to maintain.
Improved usability
If a class has multiple responsibilities and it is required to be used in other parts of the application for using a certain responsibility, it may adversely expose other responsibilities which may not be desired. It can lead to undesired behaviour in the application e.g. security and data privacy issues.
If the class follows the SRP principle strictly then unnecessary functionality will not be exposed and it makes the class more usable without fearing adverse effects.
Example 2
Here is another, similar example of a Student class that violates the SRP principle. This class is responsible for not only storing student data but also calculating fees, reporting attendance, and saving Student data to the database. Every time there is a change in fee calculation logic this class will be modified.
public class Student {
private String firstName;
private String lastName;
private int age;
public long calculateFee();
public void save();
public String reportAttendance();
}
}
To fix this, you can move out different functionalities into different classes, for example, you can create a FeeCalculator class which can take an Employee object and calculate the fee for him or her. Similarly, you can create AttendanceCalculator class to calculate attendance and a Persister class to save student objects.
public class Student {
private String firstName;
private String lastName;
private int age;
}
public class FeeCalculator{
public long calculateFee(Student s){
// fee calculation logic
}
}
public class AttendanceCalculator{
public String reportAttendance(Student s);{
// attendance calculation logic
}
}
public class StudentRepository{
public void save(Student s){
// save student object to DB/File
}
}
Multiple Choice Questions
1. Single-responsibility Principle (SRP) states:
a) A class can have multiple reasons to change, meaning that a class can have multiple jobs.
b) A class can have many functionalities.
c) A class should have one and only one reason to change, meaning that a class should have only one job.
d) None of the above.
Answer (c)
2. Select the benefits of the Single Responsibility Principle.
- It makes your software easier to implement and prevents unexpected side effects of future changes.
- It reduces the number of bugs, improves your development speed, and makes your life as a software developer a lot easier.
a) I
b) Both
c) None of the above
Answer (c)
3. Which statement is not true for SRP?
a) If your class implements multiple responsibilities, they are no longer independent of each other.
b) If your class implements single responsibility, then the class is independent of Classes, software components and microservices that have only one responsibility are much easier to explain, understand and implement than the ones that provide a solution for everything.
c) The single responsibility principle is an important rule to make your code more understandable.
Answer (a)
4. If the class follows the SRP principle strictly
a) Then unnecessary functionality will not be exposed and it makes the class be more usable without fearing adverse effects.
b) Then all the necessary functionality will be exposed and it makes the class be more usable without fearing adverse effects.
c) Both
d) None of the above
Answer (a)
5. SRP-compliant code leads
a)To a lesser number of classes that are larger in size.
b) To a greater number of classes that are smaller and more directed in scope.
c) very bad code
d) Complicated code
Answer (b)
References
- https://howtodoinjava.com/design-patterns/single-responsibility-principle/
- https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design
- https://howtodoinjava.com/design-patterns/single-responsibility-principle/
- http://blog.cleancoder.com/
- https://towardsdatascience.com/the-single-responsibility-principle-in-python-d0ab0a681853
- https://javarevisited.blogspot.com/2017/04/single-responsibility-principle-example.html#ixzz7crukwDLK