단일 책임 원칙
Single Responsibility Principle, SRP
“어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다” - 로버트 C. 마틴
'하나의 객체는 단 하나의 책임을 가져야 한다'
왜? 객체는 꼭 하나의 책임을 가져야 하는 걸까요?
단 하나의 책임을 갖는 객체
위 원칙을 이해하기 위해 한번 우리 사람을 대상으로 생각해 보겠습니다.
한번 생각해 본적 있나요? 우리가 살아가는데 얼마나 많은 역할 및 책임을 다하고 있는지를?
저만 예를 들어봐도 아들, 남동생, 개발자, 친구, 예비군, 남자친구(?)... 아무튼 셀수 없이 많은 역할 및 책임을 가지고 있습니다.
그럼 저를 클래스화 해볼까요?
class 사람속성 : 성별, 나이, 주민번호, 주소...기능 : 효도하기, 안부묻기, 코드 리뷰하기, 등산하기, 게임하기, 훈련하기, 데이트하기...
만약 제가 예비군 훈련을 하다 다리를 다치거나 혹은 여자친구와 헤어졌다면?
그 여파가 모든 기능에 영향을 미치지 않을까요?
따라서 회사-개발자, 국방부-예비군, 여자친구-남자친구 이런식으로 개발자 클래스, 예비군 클래스, 남자친구 클래스와 같이 역할과 책임을 클래스별로 분리하여 연관이 있는 클래스와 각각 따로 관계를 맺는 것이 서로 영향을 미치지 않아서 좋지 않을까요?
단일 책임 원칙을 위반한 계산기
원칙 위반 증상
기능 변경이 발생했을 때 연쇄적으로 코드를 수정해야 합니다.기능이 너무 복잡해서 재사용하기 어렵습니다.메서드의 크기가 비대해 집니다.
public class Calculator {
public int calculate(String operator, int firstNumber, int secondNumber) {
int answer = 0;
if(operator.equals("+")){
answer = firstNumber + secondNumber;
}else if(operator.equals("-")){
answer = firstNumber - secondNumber;
}else if(operator.equals("*")){
answer = firstNumber * secondNumber;
}else if(operator.equals("/")){
answer = firstNumber / secondNumber;
}
return answer;
}
}
public class Client {
public static void main(String[] args) {
Calculator calculator = new Calculator();
int firNum = 140;
int secNum = 60;
String operator = "+";
int answer = calculator.calculate(operator, firNum, secNum);
System.out.println(operator + " answer = " + answer);
operator = "-";
answer = calculator.calculate(operator, firNum, secNum);
System.out.println(operator + " answer = " + answer);
operator = "*";
answer = calculator.calculate(operator, firNum, secNum);
System.out.println(operator + " answer = " + answer);
operator = "/";
answer = calculator.calculate(operator, firNum, secNum);
System.out.println(operator + " answer = " + answer);
}
}
Calculator 에게 주어진 책임과 역할이 너무 큽니다.
각각의 연산자의 연산 과정에 변화가 생겼을 때 calculate 메서드의 크기가 비대해 지거나 다른 연산 과정에 영향을 미칠 수 있습니다.
원칙 적용 방법
더하기, 빼기, 곱하기, 나누기 연산을 기능별로 연산 클래스를 구현합니다.
계산기 클래스는 계산을 진행할 때 연산 클래스들을 이용합니다.
AddOperation : +operate : 메서드
SubstractOperation : -operate : 메서드
MultiplyOperation : *operate : 메서드
DivideOperation : /operate : 메서드