SRP (Single Responsibility Principle)
SRP, Single Responsibility Principle<br/>
(단일 책임의 원칙)
클래스는 단 하나의 책임을 가져야 한다.<br/>
책임은 해야하는 것이다<br/>
책임은 변경의 이유이다
<br/>
#Before branch
<img alt="" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/E91LXU181224235521.JPG" style="width:470px">
AreaCalculator는 도형의 넓이값을 더해주는 연산을 하는 클래스이다.<br/>
<br/>
<br/>
AreaCalcuator.java
package com.cglee079.srp;
import java.util.ArrayList;
import java.util.Iterator;
public class AreaCalculator {
private ArrayList shapes = new ArrayList();
public void calcuate(){
Iterator iter = shapes.iterator();
double areasum= 0.0;
while(iter.hasNext()){
Shape curShape = iter.next();
areasum += curShape.area();
}
System.out.println(areasum);
}
public void addShape(Shape s){
shapes.add(s);
}
}
<br/>
SRP 원칙은 하나의 클래스에 하나의 책임을 가지는 것을 말한다.<br/>
책임은 변경의 이유이다<br/>
위의 AreaCalculator클래스는 SRP원칙에 위배됨을 보인다<br/>
변경의 이유를 두가지 가지고 있기 때문이다.<br/>
<br/>
하나는, shape 넓이의 합을 계산하는 연산과<br/>
다른 하나는, 넓이의 합을 출력하는 출력문이다 <br/>
예를 들어, 연산이 합이 아닌 곱을 계산하는 클래스로 바꾼다 가정한다면<br/>
AreaCalculator 클래스의 코드는 변경되어야 할 것이다.<br/>
또한, 결과값의 출력문을 바꾸고자 한다면<br/>
AreaCalculator 클래스의 코드는 변경되어야 할 것이다.
이렇듯 변경의 이유를 2가지를 가지기 때문에 2가지의 책임을 가진다 할 수 있다.<br/>
(*반대로, 프로그래머가 출력문을 앞으로 절대로 안바꿀 것이라고 가정해보자,<br/>
그렇다면 위 클래스의 변경의 이유는 하나이며 하나의 책임을 가질 것이다.<br/>
그러므로 위 클래스는 SRP원칙에 위배되지 않을 것이다.)
<br/>
그렇다면 왜 클래스는 하나의 책임을 가져야 할까?<br/>
예를 들어서, 하나의 클래스가 100개의 책임을 가진다고 가정해보자<br/>
이 때, 이 클래스에 변경사항이 생긴다면<br/>
이 변경사항에 대하여 100개의 책임에 대한 모든 코드를 테스트 해야 할 것이다.<br/>
<br/>
#After branch
<img alt="" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/BQDJZL181224235521.JPG" style="width:470px"><br/>
AreaCalculator 클래스를 SRP원칙에 위배되지 않게 하기 위하여 <br/>
ConsolePrinter 클래스를 만들었다 <br/>
<br/>
책임을 분리하여<br/>
AreaCalculaotor 클래스는 연산을<br/>
ConsolePrinter는 결과 값을 받아 출력하는 책임을 가진다<br/>
AreaCalculator.java
package com.cglee079.srp;
import java.util.ArrayList;
import java.util.Iterator;
public class AreaCalculator {
private ArrayList shapes= new ArrayList();
private double areasum;
public double getAreasum() {
return areasum;
}
public void calcuate(){
Iterator iter= shapes.iterator();
areasum = 0.0;
while(iter.hasNext()){
Shape curShape = iter.next();
areasum += curShape.area();
}
}
public void addShape(Shape s){
shapes.add(s);
}
}
<br/>
출력문을 제외하였다.<br/>
이제 AreaCalculator 클래스는 계산을 하는 하나의 책임을 가진다.<br/>
ConsolPrinter가 areasum을 참조 할 수 있도록 클래스 필드로 선언하였다 <br/>
<br/>
ConsolePrinter.java
package com.cglee079.srp;
public class ConsolePrinter {
private AreaCalculator calculator;
public void setCalculator(AreaCalculator calculator){
this.calculator = calculator;
}
public void print(){
System.out.println("result : " + calculator.getAreasum());
}
}
<br/>
<br/>
ConsolePrinter는 AreaCalculator의 객체를 참조한다.<br/>
AreaCalculator get메소드를 호출하여 넓이의 값을 출력한다.