인프런에서 주최하는 Warming-up 클럽 0기 백엔드 스터디에 참여하고 있다.
스터디에 참여하면서 배우게 된 내용을 전체적으로 정리하고 과제로 수행했던 내용들을 정리해 보고자 한다.
(1) 5일 차 : 2024-02-23(Fri)
1. 과제 수행 : 문제 1번
(1) 아래는 주사위 게임의 코드이다. 현재 코드를 보면 전혀 리팩토링이되어 있지 않고 단순 요구사항만을 빠르게 구현하기 위해 코드의 가독성, 클린 코드 등이 전혀 적용되지 않은 코드이다.
(2) 해당 코드는 현재 사용자로부터 카운트를 입력받고, 카운트 수에 따라 주사위를 던진다.
(3) 각각 나온 주사위의 눈의 수가 몇 번 등장했는지 출력하는 게임의 코드이다.
(4) 문제 요구 사항
아래의 코드가 만약 주사위의 눈의 수가 30 또는 100까지 늘어난다면? 요구사항 수정에 의한 코드 변경 파급력이 급격하게 커지게 된다. 변경에 의한 파급력이 최대한 작아지게, 또한 읽기 좋게 코드를 수정하려면 어떻게 해야 할까? 아래의 코드를 개선된 클린 코드로 리팩토링해 보자.
2-1. 우선 Scanner로 입력을 받지 않고 본인은 BufferedReader를 사용한다.
public class GameMain {
public static void main(String[] args) throws IOException {
System.out.print("반복 횟수를 입력해 주세요 : ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int count = Integer.parseInt(br.readLine());
int d1 = 0, d2 = 0, d3 = 0, d4 = 0, d5 = 0, d6 = 0;
for (int i = 0; i < count; i++) {
int randomDiceNumber = (int) (Math.random() * 6);
if (randomDiceNumber >= 1 && randomDiceNumber < 2) {
System.out.println(randomDiceNumber);
d1++;
} else if (randomDiceNumber >= 2 && randomDiceNumber < 3) {
System.out.println(randomDiceNumber);
d2++;
} else if (randomDiceNumber >= 3 && randomDiceNumber < 4) {
System.out.println(randomDiceNumber);
d3++;
} else if (randomDiceNumber >= 4 && randomDiceNumber < 5) {
System.out.println(randomDiceNumber);
d4++;
} else if (randomDiceNumber >= 5 && randomDiceNumber < 6) {
System.out.println(randomDiceNumber);
d5++;
} else if (randomDiceNumber >= 6 && randomDiceNumber < 7) {
System.out.println(randomDiceNumber);
d6++;
}
}
// 결과 출력
System.out.printf("1은 %d번 나왔습니다.\n", d1);
System.out.printf("2는 %d번 나왔습니다.\n", d2);
System.out.printf("3은 %d번 나왔습니다.\n", d3);
System.out.printf("4는 %d번 나왔습니다.\n", d4);
System.out.printf("5는 %d번 나왔습니다.\n", d5);
System.out.printf("6은 %d번 나왔습니다.\n", d6);
br.close();
}
}
(1) 입력을 BufferedReader로 받고, 변수명도 직관적이게 조금 수정해 보았고, 수정된 코드는 위와 같다. 하지만 아직도 코드를 개선해야 겠다는 생각이 치솟는다.
(2) 우선 결과는 원하는 대로 잘 나온다. 하지만 코드를 개선해야 하는 것이 시급하다 어떻게 해야 할까?
(2) 곰곰히 생각해 보았을 때 핵심은, 사용자에게 횟수를 입력받고, 그 횟수만큼 주사위를 던진다.
(3) 던지면서 나온 눈의 수를 카운트해서 각 눈의 수에 대한 카운트값을 뿌려주기만 하면 된다.
(4) 어떻게 할 수 있을까?
3. 개선 : 자료구조 중 하나인 배열을 활용해 본다.
public class GameMainByRefactoring {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.printf("반복 횟수를 입력해 주세요 : ");
int count = Integer.parseInt(br.readLine()); // 10
System.out.printf("주사위의 최대 눈의 수를 입력하세요 : ");
int maxDiceNumber = Integer.parseInt(br.readLine());
int[] appearanceDiceNumber = new int[maxDiceNumber];
for (int i = 0; i < count; i++) {
int randomDiceNumber = (int) (Math.random() * maxDiceNumber) + 1 ; // 1~6
appearanceDiceNumber[randomDiceNumber - 1]++;
}
// 결과 출력
for (int i = 0; i < maxDiceNumber; i++) {
System.out.printf("%d은(는) %d번 나왔습니다.\n", (i + 1), appearanceDiceNumber[i]);
}
br.close();
}
}
(1) 우선 반복 횟수와 주사위에서 나올 최대 눈의 수(수의 범위)를 직접 사용자한테 입력받도록 설정한다.
(2) 이후 최대로 나올 수 있는 눈의 수까지 입력받는다.
(3) 이후의 나온 수를 대상으로 배열의 인덱스와 매핑시켜서 해당 수가 나올 때마다 카운트 수를 하나씩 증가시킨다.
(4) 결과를 출력할 때 최대 눈의 수만큼 반복을 돌려서 각 수들이 몇 번 나왔는지 카운트 수를 체크함에 따라 확인할 수 있게 된다.
(5) 처음엔 반복문으로 눈의 수가 나올 때마다 카운트를 증가시키는 부분과 결과를 출력하는 부분을 별도의 메서드로 추출할까도 생각해 봤지만 직접 해보니 코드가 이전보다 읽기 어려워진 것 같아서 메서드로 따로 뽑는 것은 하지 않으려고 한다.
(6) 위의 코드를 통해 사용자는 게임 횟수, 최대 눈의 수만 결정해주면 손쉽게 결과를 확인할 수 있고 게임 횟수, 눈의 수가 늘어나더라도 코드의 변경 파급효과가 일어나지 않는다.
(7) 이제 결과를 확인해 보자.
(8) 이전과 동일하게 결과가 정상 출력되는 것을 확인할 수 있었다.
4. 개인 회고
(1) 단순한 주사위 게임에 대한 코드이지만 이러한 코드도 클린 코드로 개선하고자 한다면 가능하다.
(2) 걱정되는 건 내가 적은 위의 리팩토링 코드가 과연 옳은 코드일지는 의문이다.
(3) 확실한 건 이전 코드보다는 읽기가 좋아졌고, 요구사항 변경 시 코드 변경의 파급력이 낮아졌다는 건 긍정적인 요소인 것 같다.
(4) 더 좋은 코드를 위해 노력하는 자세가 필요할 것 같다.
※ 해당 포스팅에 대해 내용 추가가 필요하다고 생각되면 기존 포스팅 내용에 다른 내용이 추가될 수 있습니다.
개인적으로 공부하며 정리한 내용이기에 오타나 틀린 부분이 있을 수 있으며, 이에 대해 댓글로 알려주시면 감사하겠습니다!
'기록, 회고 > InFlearn Warming-up 0기 BE' 카테고리의 다른 글
[6일 차] - 과제 수행 : Controller - Service - Repository 분리 (0) | 2024.02.23 |
---|---|
[6일 차] - 내용 정리, 개인 회고 (0) | 2024.02.23 |
[5일 차] - 내용 정리, 개인 회고 (0) | 2024.02.21 |
[4일 차] - 과제 수행 : API 개발 연습 (0) | 2024.02.21 |
[4일 차] - 내용 정리, 개인 회고 (0) | 2024.02.21 |
댓글