Single Responsibility Principle (SRP)
Every class should have only one responsibility.
SOLID principles:
- Open/closed principle (OCP)
- Liskov substitution principle (LSP)
- Interface segregation principle (ISP)
- Dependency inversion principle (DIP)
Every class should have only one responsibility.
Consider an example:
(not for production, illustrative purposes only)
class Calculator {
public void add(int x, int y) {
System.out.println(x + y);
}
}
First of all, there's a word "calculator
". "Calculator
" means "a thing aimed to calculate something". Don't be confused with what Casio does. These are not calculators, these are calculating machines. Since calculator should calculate, and what we have in the code above appears to be a sort of calculating machine, the first idea to appear in our head should be "OK, the author of this class has lied, he wanted to call it a calculating machine". So, we read it as:
(not for production, illustrative purposes only)
class CalculatingMachine {
public static void add(int x, int y) {
System.out.println(x + y);
}
}
Now everything looks great. It's time to remember SRP: every class should have only one responsibility. What responsibilities does this class have?
- It is responsible for the logic to add 2 numbers.
- It is responsible for displaying the result.
- It is responsible for choosing the output stream.
There are three responsibilities, so SRP is violated. The responsibilities described here are basically "the facts" I've mentioned in the very beginning. The idea is to write three classes so that each of them was responsible for one fact. (not for production, illustrative purposes only)
class Calculator { // this class is only responsible for adding numbers
public static int add(int x, int y) {
return x + y;
}
}
class PrintStreamDecider { // this class is only responsible for deciding
// which PrintStream is to be used
public static PrintStream getPrintStream() {
return System.out;
}
}
class ResultPrinter { // this class is only responsible for printing int values
public static void printResult(int value) {
PrintStreamDecider.getPrintStream().print(value);
}
}
We also need a fourth class to implement a calculating machine:
class CalculatingMachine { // this class is only responsible for processing the add-two-numbers request
public static void processTheAddCommand(int x, int y) {
int result = Calculator.add(x, y);
ResultPrinter.printResult(result);
}
}
CalculatingMachine
is not aware of what the "add" operation is, it is only aware of the intention.CalculatingMachine
is not aware of what isPrintStream
, it is not aware about how to print the result at all. It is only aware of the intention that result should be printed.
I'd like to emphasize that I understand that this code is completely awful. There are reasons I decided to use this approach.