워밍업 클럽 - 백엔드 5일차 과제
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! 강의 5일차 과제입니다.
문제. 다음과 같은 코드를 더 좋은 코드로 바꿔보자
제시된 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
System.out.print("숫자를 입력하세요 : ");
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0;
for (int i = 0; i < a; i++) {
double b = Math.random() * 6;
if (b >= 0 && b < 1) {
r1++;
} else if (b >= 1 && b < 2) {
r2++;
} else if (b >= 2 && b < 3) {
r3++;
} else if (b >= 3 && b < 4) {
r4++;
} else if (b >= 4 && b < 5) {
r5++;
} else if (b >= 5 && b < 6) {
r6++;
}
}
System.out.printf("1번 눈금이 %d번 나왔습니다.\n", r1);
System.out.printf("2번 눈금이 %d번 나왔습니다.\n", r2);
System.out.printf("3번 눈금이 %d번 나왔습니다.\n", r3);
System.out.printf("4번 눈금이 %d번 나왔습니다.\n", r4);
System.out.printf("5번 눈금이 %d번 나왔습니다.\n", r5);
System.out.printf("6번 눈금이 %d번 나왔습니다.\n", r6);
}
}
실행 결과
위의 코드를 실행해보니 주사위를 몇 번 던질지 받은 후 나온 눈금별로 출력해주는 프로그램이었다.
고치고 싶은 점
일단 먼저 소스코드를 봤을 때 고치고 싶은 것은 다음과 같았다.
입력을 받을 때 문구를 "주사위를 몇 번 돌릴까요?"처럼 이해하기 쉽게 바꾸면 좋을 것 같다.
상수(혹은 리터럴)은 나중에 수정하기 쉽게 밖으로 빼두면 좋을 것 같다.
변수명이 의미가 없다.
결과값을 저장하는 변수들을 배열로 바꾸면 더 깔끔할 것 같다.
마지막 결과값을 표준 출력하는 부분은 반복문을 이용하여 중복 코드를 제거할 수 있을 것 같다.
주사위를 돌리는 로직을 짧게 단순화할 수 있을 것 같다.
Scanner를 close를 명시적으로 해서 더 안전하고 확실하게 관리할 수 있을 것 같다.
1차 수정
import java.util.Scanner;
public class Main {
// 상수들
private static final int NUMBER_OF_FACES = 6; // 12
private static final String PROMPT_MESSAGE = "주사위를 몇번 돌릴까요? (Hint: 숫자 입력) ";
private static final String RESULT_MESSAGE_FORMAT = " => %d번 눈금이 %d번 나왔습니다.\n";
public static void main(String[] args) throws Exception {
System.out.print(PROMPT_MESSAGE);
try (Scanner scanner = new Scanner(System.in)) {
// 입력
int count = scanner.nextInt();
// 주사위 돌렸을 때의 결과 저장
int[] rollResults = new int[NUMBER_OF_FACES];
for (int i = 0; i < count; i++) {
int resultFace = (int)(Math.random() * NUMBER_OF_FACES);
rollResults[resultFace]++;
}
// 결과 출력
for (int i = 0; i < NUMBER_OF_FACES; i++) {
System.out.printf(RESULT_MESSAGE_FORMAT, i+1, rollResults[i]);
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
위의 내용들을 반영하여 수정하여 더 가독성이 좋고 깔금하게 만들었다.
그리고 더 안정적이다. 명시적 close 말고 예전에 썼던 파이썬 with 문처럼 블록이 끝나면 자원을 방출해주는 기능이 자바에도 있는 걸 발견해서 추가로 적용했다.
상수를 빼내어서 추가 요구사항인 12면체 주사위를 만들기 쉬워졌고 문자열도 바꾸기 쉽다.
실행 결과
일반 주사위
12면체 주사위
2차 수정
코드의 역할별로 메서드로 추출했다.
import java.util.Scanner;
public class Main {
private static final int NUMBER_OF_FACES = 6; // 12
private static final String PROMPT_MESSAGE = "주사위를 몇번 돌릴까요? (Hint: 숫자 입력) ";
private static final String WRONG_INPUT_MESSAGE = " ** 프로그램을 종료합니다. **\n => Hint. 0 이상의 숫자를 입력하세요.";
private static final String RESULT_MESSAGE_FORMAT = " => %d번 눈금이 %d번 나왔습니다.\n";
public static void main(String[] args) {
int count = getUserInput();
int[] rollResults = rollDice(count);
printResults(rollResults);
}
private static int getUserInput() {
System.out.print(PROMPT_MESSAGE);
try (Scanner scanner = new Scanner(System.in)) {
int input = scanner.nextInt();
if (input < 0) {
System.out.println(WRONG_INPUT_MESSAGE);
return 0;
}
return input;
} catch (Exception exception) {
System.out.println(WRONG_INPUT_MESSAGE);
return -1;
}
}
private static int[] rollDice(int count) {
int[] rollResults = new int[NUMBER_OF_FACES];
for (int i = 0; i < count; i++) {
int resultFace = (int)(Math.random() * NUMBER_OF_FACES);
rollResults[resultFace]++;
}
return rollResults;
}
private static void printResults(int[] rollResults) {
for (int i = 0; i < NUMBER_OF_FACES; i++) {
System.out.printf(RESULT_MESSAGE_FORMAT, i + 1, rollResults[i]);
}
}
}
역할별로 메서드를 추출해서 좀 더 관련 있는 부분을 수정하거나 검증하기 쉬워졌다.
유저의 입력을 받는 getUserInput 부분에서 간단하게 잘못된 입력이 들어온 경우에 대한 예외 처리를 해주었다.
실행 결과
옳은 입력
잘못된 입력
댓글을 작성해보세요.