인프런 워밍업 클럽

인프런 워밍업 클럽/ BE 5일차 과제 : 클린 코드

킹갓홍 2024. 5. 9. 18:19

5일차 과제

출처 : 인프런 -  자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

 


우선 위의 정리되지 않은 코드를 개선하기 위해 아래와 같이 기능별로 메서드를 나누기로 했다.

큰 기능별로 메서드를 나누게 되면 나중에 에러가 발생했을 경우, 어느 메서드에서 에러가 났는지 확인하는 것으로 어떤 기능이 에러인지 바로 확인할 수 있다. 만약 inputNumber 메서드에서 에러가 발생했다면 "아 숫자를 입력하는 로직에서 에러가 발생했구나" 라는 것을 직관적으로 알 수 있게 된다. 

import java.util.Scanner;

public class Main {
    static Scanner scanner = new Scanner(System.in);
    static int[] countNumbers;

    public static void main(String[] args) throws Exception {
        int number = inputNumber();
        throwDice(number);
        showResult();
    }

    private static int inputNumber() {
        System.out.print("던질 횟수를 입력하세요 : ");
        return scanner.nextInt();
    }
    
    private static void throwDice(int number) {
        countNumbers = new int[6];

        for(int count=0; count<number; count++) {
            int diceNumber = (int)(Math.random()*6);
            countNumbers[diceNumber]++;
        }
    }
    
    private static void showResult() {
        StringBuilder result = new StringBuilder();
        for(int diceNumber=0; diceNumber<=5; diceNumber++) {
            result.append((diceNumber+1)+"번이 나온 횟수 : "+countNumbers[diceNumber]+"\n");
        }
        System.out.println(result);
    }
    
}

위에서 나눴던대로 3개의 메서드를 만들었고 전역변수로 Scanner객체와 각 주사위번호가 몇번 나왔는지 확인하는 countNumbers 배열 객체를 만들었다.

 

📌그러면 왜 number값은 전역변수로 두지 않았나?

number변수는 사용자와 직접적으로 상호작용하는 변수이기 때문에 비즈니스 로직에서 해당 부분이 사용자가 입력하면서 생성되고 있다는 뉘앙스(?)를 위해서 전역변수로 두지 않았다.

 

inputNumber메서드

사용자가 주사위를 몇 번 던질지 입력하는 과정이다.

간단하게 scanner.nextInt()라는 메서드를 사용할 수 있으나, 코딩에 대해 모르는 사람이 봐도 직관적으로 무슨 일을 처리하는 메서드인지 알 수 있도록 하기 위해서 메서드를 만들어서 이름을 부여했다.

 

throwDice메서드

사용자가 설정한 횟수를 가지고 랜덤으로 주사위를 던지는 과정이다.

전역변수로 뒀던 countNumbers를 초기화하고, 랜덤으로 나오는 주사위 눈 값을 인덱스로 해서 countNumbers을 시킨다. 

 

showResult메서드

결과값을 출력하는 메서드이다.

StringBuilder객체를 생성하고 countNumbers를 순회하면서 각 주사위가 몇번 나왔는지 StringBuilder 객체에 저장하고 마지막에 출력한다.

 

결과값


📌한걸음 더

 

위에 리팩토링한 코드들은 사실 주사위의 눈이 6개라고 상정하고 작성한 코드이다. 

때문에 throwDice메서드에서 countNumbers배열의 크기도 6으로 했고, 랜덤 주사위값이 6까지만 나오도록 했다.

 

이것을 사용자가 원하는 주사위의 크기로 설정해서 주사위의 크기가 커져도 동적으로 바꿀 수 있도록 해보자.

import java.util.Scanner;

public class Main {
    static Scanner scanner = new Scanner(System.in);
    static int[] countNumbers;

    public static void main(String[] args) throws Exception {
    	// 입력
        int diceSize = inputDiceSize();
        int number = inputNumber();
        
    	// 주사위 던지기
        throwDice(diceSize,number);
       	
    	// 출력
        showResult(diceSize);
    }
    private static int inputDiceSize() {
        System.out.print("주사위 눈의 수를 입력하세요 : ");
        return scanner.nextInt();
    }
    private static int inputNumber() {
        System.out.print("던질 횟수를 입력하세요 : ");
        return scanner.nextInt();
    }
    private static void throwDice(int diceSize, int number) {
        countNumbers = new int[diceSize];
        for(int count=0; count<number; count++) {
            int diceNumber = (int)(Math.random()*diceSize);
            countNumbers[diceNumber]++;
        }

    }
    private static void showResult(int diceSize) {
        StringBuilder result = new StringBuilder();
        for(int diceNumber=0; diceNumber<diceSize; diceNumber++) {
            result.append((diceNumber+1)+"번이 나온 횟수 : "+countNumbers[diceNumber]+"\n");
        }
        System.out.println(result);
    }
}

기존 코드에서  사용자로부터 주사위 눈의 수를 입력받는 것을 추가하고 주사위 눈의 크기를 메서드들에게 같이 넘겨주게 했다. 이렇게 되면 주사위 눈의 크기를 동적으로 할당해서 사용자가 원하는 크기의 주사위를 쓸 수 있게 된다. 

 

결과값

 

 

강의 출처 : https://www.inflearn.com/course/%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%84%9C%EB%B2%84%EA%B0%9C%EB%B0%9C-%EC%98%AC%EC%9D%B8%EC%9B%90/dashboard