The Single Responsibility Principle

The principle says: "A module should be responsible to one, and only one, actor."

All right, but what a "actor" and "module" should mean?

Here a example:

Suppose a class Employee like:

public class Employee {
    public BigDecimal calculatePay(){
        // do calculations stuffs here
    }

    public Double reportHours() {
        // do hours magic
    }

    public Employee save(){
        // save on the database
    }

    public Doubole regularHours(){}
}

Note

All the examples will be in java. Just for OOP world compliance :)

Now, this class is consumed by three different actors: CFO (uses calculatePay()); COO (uses reportHours()) and the CTO (uses the save()). When the developers of the class Employee coded this methods in the same class, they coupled the actors on each other.

For instance: suppose that calculatePay() and reportHours() share a common algorithm defined in regularHours() method. When the CFO asks for a minor changes in the pay calculation, that needs to change the behaviour of the regularHours() method, it cannot be done without changing the reportHours() output. If a developer blindly change the method and don't have a good test coverage the team will be serious problems when the COO use the reportHours method.

That's not the kind of thing a system should do. But, how can we fix it?

There is no optimal or best solution, each programmer can handle this in different ways. Here are some possible solutions:

A straightforward solution is segregating the data from methods, and isolating them in their own classes, like:

record EmployeeData(/*Employee data here*/){}

class PayCalculator {
	public calculatePay(EmployeeData data){}
}


class HourReporter {
	public reportHours(EmployeeData data){}
}


class EmployeeSaver {
	public saveEmployee(EmployeeData data){}
}

This is good, but now we have three more classes to initialize and handle. Another solution is using the Facade Pattern:

record EmployeeData(/*Employee data here*/) {}

class PayCalculator {
	public calculatePay(EmployeeData data) {}
}


class HourReporter {
	public reportHours(EmployeeData data) {}
}


class EmployeeSaver {
	public saveEmployee(EmployeeData data) {}
}

class EmployeeFacade {
	private PayCalculator payCalculator;
	private HourReporter hourReporter;
	private EmployeeSaver employeeSaver;
	
	public EmployeeFacade(PayCalculator payCalculator, HourReporter hourReporter, EmployeeSaver employeeSaver) {
		this.payCalculator = payCalculator;
		this.hourReporter = hourReporter;
		this.employeeSaver = employeeSaver;
	}
	
	public calculatePay(EmployeeData data) {
		return this.payCalculator.calculatePay(data);
	}

	public reportHours(EmployeeData data) {
		return this.hourReporter.reportHours(data);
	}

	public saveEmployee(EmployeeData data) {
		return this.employeeSaver.saveEmployee(data);
	}
}

Some folks prefer closing the data to the main business rules, like:


class HourReporter {
	public reportHours(Employee data) {}
}


class EmployeeSaver {
	public saveEmployee(Employee data) {}
}

class Employee {
	private HourReporter hourReporter;
	private EmployeeSaver employeeSaver;
	/*some data here*/
	
	public Employee(HourReporter hourReporter, EmployeeSaver employeeSaver) {

		this.hourReporter = hourReporter;
		this.employeeSaver = employeeSaver;
	}
	
	public calculatePay() {
		/*Calculate Pay*/
	}

	public reportHours(Employee data) {
		return this.hourReporter.reportHours(data);
	}

	public saveEmployee(Employee data) {
		return this.employeeSaver.saveEmployee(data);
	}
}

You could think that's strange, some classes have only one public method, but Don't Panic! The number of methods to save, calculate pay and report hours probably will be huge in each situation. Each of these classes should have their own private methods, in that way, each "family" of methods are a scope, outside this scope no one know the private methods :)