728x90
1. 1차 실습 코드(caclulator_v1)
package calculator_v1;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Scanner;
import static org.assertj.core.api.Assertions.assertThat;
public class RealCalculator {
public static Calculator calClass = new Calculator();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String line = in.nextLine();
int calResult = calculator(line);
System.out.println(calResult);
}
public static int calculator(String text){
int total = 0;
String[] split_text = text.split(" ");
if(split_text.length > 0){
total = Integer.valueOf(split_text[0]);
for(int i = 1; i < split_text.length; i++){
int num2 = Integer.valueOf(split_text[i+1]);
String str = split_text[i];
total = calClass.cal(total, str, num2);
i = i+1;
}
}
return total;
}
}
package calculator_v1;
public class Calculator {
public int cal(int num1, String type, int num2){
int result = 0;
switch(type){
case "+":
result = plus(num1, num2);
break;
case "-":
result = minus(num1, num2);
break;
case "*":
result = multiply(num1, num2);
break;
case "/":
result = divide(num1, num2);
break;
}
return result;
}
public int plus(int i, int j){
return i + j;
}
public int minus(int i, int j){
return i - j;
}
public int multiply(int i, int j){
return i * j;
}
public int divide(int i, int j){
try{
return i / j;
}catch (Exception e){
System.out.println(j + "로 나눌 수 없습니다.");
}
return 0;
}
}
main 메서드를 이용해서 "2 + 3 * 4 / 2" 실행 결과인 10을 출력을 했지만, 테스트 코드를 활용하지 못해서 다시 되도림표로 돌아왔다.
다른 블로그 글을 참고하면서 현재 코드에서 리팩토링 되어야 할 부분을 정리해 보았다.
[1차 리팩토링 할 부분]
- Test코드와 실제 운영되는 코드 분리하기(src/main/java 패키지와 src/test/java 패키지 용도에 맞춰서 분리하기)
- 예외 처리하기
- 입력 값이 빈 값이거나 null일 경우 -> throw new IllegalArgumentException();
- switch문 default 예외 처리 -> throw new IllegalArgumentException();
- 숫자만 입력됐을 때 (예- 1 => return 1;)
- 변수 이름 변경
- Validation (사용할 수 있는 연산 부호인지 확인)
2. 2차 실습 코드(caclulator_v2)
[수정된 부분]
복잡하게 i를 계산하는 로직이 없어졌다.
변수 이름을 직관적으로 변경하여 이해하기 쉬워졌다.
테스트 코드 패키지와 분리되어서 test를 작성하고 삭제하는 행위가 없어졌다. (더 깔끔해지기도 했고..)
[src/main/java/calculator_v2]
package calculator_v2;
import java.util.Scanner;
public class RealCalculator {
public Calculator calClass = new Calculator();
private String[] operationType = {"+", "-", "*", "/"};
public Integer calculator(String formula){
int result = 0;
String[] split_text = formula.split(" ");
if(split_text.length > 0){
result = Integer.valueOf(split_text[0]);
String operator = "";
for(int i = 1; i < split_text.length; i++){
String input_i = split_text[i+1];
if(input_i.isEmpty()){
throw new IllegalArgumentException();
}
if(isPermittedOperator(input_i)){
operator = input_i;
}else{
int num2 = Integer.valueOf(input_i);
result = calClass.cal(result, operator, num2);
}
}
}
return result;
}
private boolean isPermittedOperator(String input){
for(String operator : operationType){
if(input.equals(operator)) return true;
}
return false;
}
}
package calculator_v2;
public class Calculator {
public int cal(int num1, String type, int num2){
int result = 0;
switch(type){
case "+":
result = plus(num1, num2);
break;
case "-":
result = minus(num1, num2);
break;
case "*":
result = multiply(num1, num2);
break;
case "/":
result = divide(num1, num2);
break;
default:
throw new IllegalArgumentException();
}
return result;
}
public int plus(int i, int j){
return i + j;
}
public int minus(int i, int j){
return i - j;
}
public int multiply(int i, int j){
return i * j;
}
public int divide(int i, int j){
try{
return i / j;
}catch (Exception e){
System.out.println(j + "로 나눌 수 없습니다.");
}
return 0;
}
}
[src/test/java/study]
package study;
import calculator_v2.RealCalculator;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CalculatorTest {
public RealCalculator rCal;
@BeforeEach
public void setUp() {
rCal = new RealCalculator();
}
@Test
public void formula_test() {
assertEquals(10, rCal.calculator("2 + 3 * 4 / 2"));
}
@DisplayName("단일 항일 경우")
@Test
public void formula_single() {
assertEquals(1, rCal.calculator("1"));
}
}
[2차 리팩토링 할 부분]
- 유틸리티 클래스와 객체 구분해서 사용하기
- 객체 지향 관점에서 최대한 클래스로 묶을 수 있는 부분은 묶자. (switch 부분, 연산하는 부분, for문으로 split 하는 부분)
- Case 별로 Test코드를 작성하기
- 인수 1개가 null 일 경우 (예 : 2 + + 4)
[참고]
1차 피드백
##### 클래스 분리 필요성 (1) ```{.java} public class StringCalculator { ``` > StringCalculator 내용을 한 클래스에 구…
wikidocs.net
'Java > TDD' 카테고리의 다른 글
[TDD] 문자열 계산기 && 2차 리팩토링 (0) | 2024.06.17 |
---|