워밍업 클럽 - 백엔드 5일차 과제

워밍업 클럽 - 백엔드 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);
    }
}

실행 결과

image위의 코드를 실행해보니 주사위를 몇 번 던질지 받은 후 나온 눈금별로 출력해주는 프로그램이었다.

 

고치고 싶은 점

일단 먼저 소스코드를 봤을 때 고치고 싶은 것은 다음과 같았다.

  1. 입력을 받을 때 문구를 "주사위를 몇 번 돌릴까요?"처럼 이해하기 쉽게 바꾸면 좋을 것 같다.

  2. 상수(혹은 리터럴)은 나중에 수정하기 쉽게 밖으로 빼두면 좋을 것 같다.

  3. 변수명이 의미가 없다.

  4. 결과값을 저장하는 변수들을 배열로 바꾸면 더 깔끔할 것 같다.

  5. 마지막 결과값을 표준 출력하는 부분은 반복문을 이용하여 중복 코드를 제거할 수 있을 것 같다.

  6. 주사위를 돌리는 로직을 짧게 단순화할 수 있을 것 같다.

  7. 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면체 주사위를 만들기 쉬워졌고 문자열도 바꾸기 쉽다.

 

실행 결과

일반 주사위

image

12면체 주사위

image


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 부분에서 간단하게 잘못된 입력이 들어온 경우에 대한 예외 처리를 해주었다.

실행 결과

옳은 입력

image

잘못된 입력

image

댓글을 작성해보세요.

채널톡 아이콘