반응형
너무 많은 if, else 는 읽기 어려운 코드가 된다 ..
이 때는 코드를 수정하기도 어렵고 코드를 디버깅할 때도 어려울 수 밖에.
if 문이 많은 코드에서 어떻게 if 문을 제거할지 한번 생각해보자.
public class CalculateCommand {
private CalculateType calculateType;
private int num1;
private int num2;
public CalculateCommand(CalculateType calculateType, int num1, int num2) {
this.calculateType = calculateType;
this.num1 = num1;
this.num2 = num2;
}
public CalculateType getCalculateType() {
return calculateType;
}
public int getNum1() {
return num1;
}
public int getNum2() {
return num2;
}
}
public enum CalculateType {
ADD, MINUS, MULTIPLY, DIVIDE
}
public class ManyIfCodeExampleMain {
public static void main(String[] args) {
CalculateCommand calculateCommand = new CalculateCommand(
CalculateType.ADD,
100,
3
); // 보통 클라이언트가 요청할 때 보내준 데이터를 사용
Client client = new Client();
int result = client.someMethod(calculateCommand);
System.out.println(result);
}
}
예제
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
int result = 0;
if(calculateType != null && calculateType.equals(CalculateType.ADD)) {
result = num1 + num2;
} else if(calculateType != null && calculateType.equals(CalculateType.MINUS)) {
result = num1 - num2;
} else if(calculateType != null && calculateType.equals(CalculateType.MULTIPLY)) {
result = num1 * num2;
} else if(calculateType != null && calculateType.equals(CalculateType.DIVIDE)) {
if(num2 == 0) {
throw new RuntimeException("0으로 나눌 수 없습니다.");
} else {
result = num1 / num2;
}
}
return result;
}
}
-> 예외처리를 했더니 사악한 코드가 만들어졌다 ... 내가 만든게 아니라면 더욱 이해하기 어렵다.
예제
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
int result = 0;
if(calculateType == null) {
return result;
}
if(calculateType.equals(CalculateType.DIVIDE) && num2 == 0) {
throw new RuntimeException("0으로 나눌 수 없습니다.");
}
if(calculateType.equals(CalculateType.ADD)) {
result = num1 + num2;
} else if(calculateType.equals(CalculateType.MINUS)) {
result = num1 - num2;
} else if(calculateType.equals(CalculateType.MULTIPLY)) {
result = num1 * num2;
} else if(calculateType.equals(CalculateType.DIVIDE)) {
result = num1 / num2;
}
return result;
}
}
예외 처리 두 가지를 앞으로 빼주었다. 개선이 많이 되었다.
예제
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
if(calculateType == null) {
return 0;
}
if(calculateType.equals(CalculateType.DIVIDE) && num2 == 0) {
throw new RuntimeException("0으로 나눌 수 없습니다.");
}
int result = calculateType.calculate(num1, num2);
return result;
}
}
public enum CalculateType {
ADD ((num1, num2) -> num1 + num2),
MINUS ((num1, num2) -> num1 - num2),
MULTIPLY ((num1, num2) -> num1 * num2),
DIVIDE ((num1, num2) -> num1 / num2);
CalculateType(BiFunction<Integer, Integer, Integer> expression) {
this.expression = expression;
}
private BiFunction<Integer, Integer, Integer> expression;
public int calculate(int num1, int num2) {
return this.expression.apply(num1, num2);
}
}
enum 클래스로 계산 로직을 옮겨서 더 개선시켰다.
클라이언트에서는 계산 로직을 알 필요가 없어진다. calcuateType 에게 파라미터만 넘겨서 calculate() 만 호출하면 된다.
예제
public class CalculateCommand {
private CalculateType calculateType;
private int num1;
private int num2;
public CalculateCommand(CalculateType calculateType, int num1, int num2) {
if(calculateType == null) {
throw new RuntimeException("CalculateType은 필수 값 입니다.");
}
if(calculateType.equals(CalculateType.DIVIDE) && num2 == 0) {
throw new RuntimeException("0으로 나눌 수 없습니다.");
}
this.calculateType = calculateType;
this.num1 = num1;
this.num2 = num2;
}
public CalculateType getCalculateType() {
return calculateType;
}
public int getNum1() {
return num1;
}
public int getNum2() {
return num2;
}
}
public class Client {
public int someMethod(CalculateCommand calculateCommand) {
CalculateType calculateType = calculateCommand.getCalculateType();
int num1 = calculateCommand.getNum1();
int num2 = calculateCommand.getNum2();
int result = calculateType.calculate(num1, num2);
return result;
}
}
-> 생성 시점에 유효성 검사 (사용 시점이 아닌 !)
이렇게 우리는 리팩토링하는 과정을 살펴보았습니다.
리팩토링 : 결과의 변경 없이 코드의 구조를 재조정 하는것.
가독성을 높이거나 유지보수를 편하게 함
근데 결과의 변경이 없다는 것을 어떻게 확인할 수 있을가?
-> 테스트 코드
반응형
'백엔드 데브코스' 카테고리의 다른 글
[Java] stream API (0) | 2023.09.26 |
---|---|
[Java] getter, setter, 생성자로 알아보는 객체지향적인 코드 (0) | 2023.09.25 |
[Java] Optional - nullPointException을 잘 다뤄보자 (0) | 2023.09.25 |
[Java] Object 클래스와 주요 메서드 - equals(), hashCode(), toString() (0) | 2023.09.22 |
[Java] Checked & Unchecked exception 의 차이 (0) | 2023.09.22 |