Single Responsibility Principle

What is „Single Responsibility Principle” (SRP)?

It is the first rule of the SOLID design rules (it stands for S in SOLID acronym).

Definition

Every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. Or in simple terms: A class or module should have one, and only one, reason to be changed.
 
Robert C. Martin (Uncle Bob)
From this quote you should remember sentence „A class or module should have once, and only one, reason to changed.” To understand it better think about Employee class like below:
 
Let’s say that:
  • calculatePay() method was prepared by accountent department,
  • reportHours() method was prepared by human resources department,
  • save() method was prepared by databases administrators.

Involving all this methods in one class violates SRP rule, because the responsibilities of three different departments are interconnected. Due to this solution, one change may cause further refactoring in other parts of code.

Solution for this problem would be architecture like below:

First what we need to do is to isolate data from methods. That is why we have created EmployeeData class, which is data struture without any methods. Employee facade is responsible for delegating tasks to other methods (for more details see facade programming pattern). PayCalculator, HourReporter and EmployeeSaver classes contain minimal code required for doing their purpose. What is important, those classes are isolated from each other.

Real-life example

Let’s say we have an application that calculates the employee’s years to retirement.

public class Launcher {

    public static void main(String[] args){
        Assistant assistant = new Assistant(30);
        assistant.handleEmployee();
    }

}
public class Assistant {

    public int retrimentAge = 65;
    public int age;

    public Assistant(int age) {
        this.age = age;
    }
    public void handleEmployee(){
        System.out.println("Logging data...");
        System.out.println(this.retrimentAge - this.age);
    }

}

Assistant class is kind of God class, which handles logging  and calculations, due to that application at this moment does not meet SRP rule.

UML for Assistant class is like below:

Let’s refactor the code according to SRP rule. We should start with separating logging and calculations to two different classes. It might also be good idea to use composition and create class for delegating the tasks.

public class Launcher {

    public static void main(String[] args){
        Assistant assistant = new Assistant(30);
        assistant.handleEmployee();
    }

}
public class Assistant {
 
    private FinanceAssistant financeAssistant;
    private Logger logger;
 
    public Assistant(int age) {
        this.financeAssistant= new FinanceAssistant(age);
        this.logger = new Logger();
    }
 
    public void handleEmployee(){
        this.logger.log();
        this.financeAssistant.calculate();
    }
}
public class Logger {
     
    public void log() {
        System.out.println("Logging data...");
    }
}
public class FinanceAssistant {
 
    public int retirementAge = 65;
    public int age;
 
    public FinanceAssistant(int age) {
        this.age = age;
    }
 
    public void calculate() {
        System.out.println(this.retirementAge - this.age);
    }
}

After code refactoring, the UML looks like:

Why should I follow „Single Responsibility Principle” ?

This rule helps to maintain the code, due to that changes are isolated. Code is less complex and therefore easier to understand and reuse.

What to look for?

SRP rule is not defined by sentence that a class should be doing only once job. It is common mistake in this rule, probably caused by a bit of a misnomer.

Posted in SOLID rulesTags:
Write a comment