이제 막 시작이고 코드에 정답은 없기에 너무 많은 시간을 투자하는 것은 지양하기로 했다. 다른 분에게 해준 피드백을 참고해서 하나의 클래스 안에 만들어야 한다는 생각은 버리고 계산 과정을 새로 만들었다. 또 ExceptionTest를 만들어 예외에 대한 테스트를 세분화하였다.
다시쓰는 경험할 객체지향 생활 체조 원칙
이번 과정을 통해 연습할 원칙은 다음 두 가지이다.
규칙 1: 한 메서드에 오직 한 단계의 들여쓰기만 한다.
규칙 2: else 예약어를 쓰지 않는다.
이 같은 원칙 아래에서 *메소드의 라인 수를 15라인이 넘지 않도록 구현한다.
왜 저 15라인을 못 본 걸까... 이번에는 제대로 적용시켰다!
public class Calculator {
public int execute() {
Scanner scanner = new Scanner(System.in);
String value;
try {
value = scanner.nextLine();
}catch (NoSuchElementException e){
throw new NoSuchElementException("공백은 입력할 수 없습니다.");
}
scanner.close();
String[] values = value.split(" ");
return throwMethod(values);
}
public int throwMethod(String[] values){
try {
return calculate(values);
} catch (ArrayIndexOutOfBoundsException e) {
throw new ArrayIndexOutOfBoundsException("입력이 잘못되었습니다.");
} catch (NumberFormatException e) {
throw new NumberFormatException("숫자 자리에 다른 문자를 입력했거나 띄워쓰기가 잘못되었습니다.");
}
}
public int calculate(String[] values) {
Operator operator;
int result = Integer.parseInt(values[0]);
int nextValue;
for (int i = 1; i < values.length; i += 2) {
String symbol = values[i];
nextValue = Integer.parseInt(values[i + 1]);
operator = Operator.findOperator(symbol);
result = operator.operate(result, nextValue);
}
return result;
}
}
public enum Operator {
ADD("+", (first, second) -> first + second),
SUBTRACT("-", (first, second) -> first - second),
MULTIPLY("*", (first, second) -> first * second),
DIVIDE("/", (first, second) -> {
if (second == 0) {
throw new ArithmeticException("0으로 나눌 수 없습니다.");
}
return first / second;
});
private String symbol;
private BiFunction<Integer, Integer, Integer> operation;
Operator(String symbol, BiFunction<Integer, Integer, Integer> operation){
this.symbol = symbol;
this.operation = operation;
}
public int operate(int first, int second){
return operation.apply(first, second);
}
public static Operator findOperator(String symbol){
for(Operator operator : Operator.values()) {
if (symbol.equals(operator.symbol)) {
return operator;
}
}
throw new IllegalArgumentException("잘못된 연산자입니다.");
}
}
예외가 아닌 계산 테스트는 기존과 달라진 점이 없으므로 ExceptionTest.java만 업로드하였다.
public class ExceptionTest {
Calculator calculator = new Calculator();
public static void inputHandling(String userInput) {
InputStream in = new ByteArrayInputStream(userInput.getBytes());
System.setIn(in);
}
@Test
void inputBlank(){
inputHandling("");
assertThatThrownBy(() -> calculator.execute())
.isInstanceOf(NoSuchElementException.class)
.hasMessage("공백은 입력할 수 없습니다.");
}
@Test
@DisplayName("계산 형식이 잘못된 입력")
void wrongInput(){
inputHandling("1 * 0 /");
assertThatThrownBy(() -> calculator.execute())
.isInstanceOf(ArrayIndexOutOfBoundsException.class)
.hasMessage("입력이 잘못되었습니다.");
}
@Test
void wrongOperator(){
inputHandling("1 C 2");
assertThatThrownBy(() -> calculator.execute())
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("잘못된 연산자입니다.");
}
@Test
void wrongNumber() {
inputHandling("ㅁ * 2");
assertThatThrownBy(() -> calculator.execute())
.isInstanceOf(NumberFormatException.class)
.hasMessage("숫자 자리에 다른 문자를 입력했거나 띄워쓰기가 잘못되었습니다.");
}
}
사용자 입력같이 세부적인 것이 정해진 것이 없어 처음에 어떻게 시작해야 할지 몰라 당황했던 기억이 난다. 요구사항이 자세했으면 편했겠지만, 1부터 100까지 모든 것을 다 정해주고 그 안에서만 행동하면 그것은 기계와 다름없다(사실 정해진 대로 하는게 편하긴 하지만..). 어서 빨리 미션 1-2인 숫자야구 게임을 구현한뒤 공통피드백을 보고싶다!