[워밍업클럽] BE 1기 #과제5

[워밍업클럽] BE 1기 #과제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);
    }
}

 

풀이 >

위의 코드가 클린하지 않은 이유는 여러 역할을 수행하고 있으며, 의미를 알 수 없는 변수를 사용하고 있다. 또한 주사위눈의 수가 6개가 아닌경우 코드 수정(횟수를 저장하는 변수 추가, if문 수정, 결과 출력문 수정)이 필요하다.

 

해당 코드에서 수행하는 역할을 크게 3개로 나눠 각각을 함수로 분리하였다.

System.out.print("숫자를 입력하세요 : ");
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int number = init();


public static int init(){
   System.out.print("숫자를 입력하세요 : ");
   Scanner scanner = new Scanner(System.in);
   return scanner.nextInt();
}

-> number를 받는 init함수를 구현하였다.

 

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++;
      }
  }

-> 기존의 코드는 변수r1~r6을 사용해 결과를 저장할때 if문으로 b값이 어느 숫자인지 확인하는 부분이 있는데, 주사위눈의 수만큼 배열을 선언하여 b값만 구한후 해당 인덱스값에 합을 누적하여 if문과 r1~r6변수를 사용하지 않도록 수정하였다.

int[] diceCountArr = getDiceCount(number);


private static int[] getDiceCount(int number) {
   int dice[] = new int[6];

   for(int i = 0 ; i < number ; i++){
      dice[(int)Math.random() * 6]++;
    }
    return dice;
}

 

코드 마지막부분에 결과를 출력하는데,

만약, 주사위눈의 개수가 변경되는 경우 System.out.printf문을 삭제하거나 추가해야한다.

  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);

 

-> 결과값 출력 부분을 배열길이만큼 for문을 수행하여 System.out.printf문을 불필요하게 늘이거나 줄이지 않고 출력하도록 printResult함수를 구현하였다.

printResult(diceCountArr);

private static void printResult(int[] diceCountArr) {
  for(int i = 0 ; i < diceCountArr.length ; i++){
     System.out.println((i + 1) + "은 " + diceCountArr[i] + "번 나왔습니다.");
  }
}

 

만약 주사위눈의 개수가 6이아니라면 배열을 초기화하는 수와 랜덤값을 구할때 곱해주는 부분을 수정해야한다.

image

static 변수 diceNumber로 주사위눈 개수를 초기화하도록 코드를 수정하였다.

주사위눈 개수를 변경하려면 diceNumber값을 수정하면되고, dice배열 초기화때 길이값과 랜덤값 계산시 해당 변수를 사용하게된다.

private static int diceNumber = 7;
private static int[] getDiceCount(int number) {
    int dice[] = new int[diceNumber];

    for(int i = 0 ; i < number ; i++){
        dice[(int)(Math.random()*diceNumber)]++;
    }
    return dice;
}

 

변경한 코드

import java.util.Scanner;

public class Main {
    private static int diceNumber = 7;

    public static int init(){
        System.out.print("숫자를 입력하세요 : ");
        Scanner scanner = new Scanner(System.in);
        return scanner.nextInt();
    }

    private static int[] getDiceCount(int number) {
        int dice[] = new int[diceNumber];

        for(int i = 0 ; i < number ; i++){
            dice[(int)(Math.random()*diceNumber)]++;
        }
        return dice;
    }

    private static void printResult(int[] diceCountArr) {
        for(int i = 0 ; i < diceCountArr.length ; i++){
            System.out.println((i + 1) + "은 " + diceCountArr[i] + "번 나왔습니다.");
        }
    }


    public static void main(String[] args) throws Exception{
        int number = init();

        int[] diceCountArr = getDiceCount(number);

        printResult(diceCountArr);

    }

}

 

 

강의

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

출처

https://mangkyu.tistory.com/132

https://ittrue.tistory.com/336

https://tasddc.tistory.com/84

https://gyoogle.dev/blog/computer-science/software-engineering/Clean%20Code%20&%20Refactoring.html

댓글을 작성해보세요.