배달의 민족 운영사인 우아한형제들에서 운영하는 개발자 양성 프로젝트, 우아한테크코스에 지원하게 되었다.
우아한테크코스 프리코스과정에 3주차의 내가 시간을 많이 투자한 부분과 느낀점, 부족한점을 작성하는 회고록이다.
🔎 2주차 피드백 정리
README.md 기능구현목록을 상세히 작성한다.
값을 하드 코딩하지 않는다.
처음부터 큰 단위의 테스트를 만들지 않는다.
- 테스트의 중요한 목적 중 하나는 내가 작성하는 코드에 대해 빠르게 피드백을 받는 것이다. 시작부터 큰 단위의 테스트를 만들게 된다면 작성한 코드에 대한 피드백을 받기까지 많은 시간이 걸린다. 그래서 문제를 작게 나누고, 그 중 핵심 기능에 가까운 부분부터 작게 테스트를 만들어 나가는것이 중요할 것이다.
함수가 한 가지 기능을 하는지 확인하는 기준을 세운다.
- 함수를 분리하는 기준이 세워지면 함수를 분리하는 것 뿐만아니라, 그 기준에 대해 해당되는 클래스만 모을수 있게 되며 mvc 모델도 선별하기 쉬울것 같다.
- 학습한 참고 자료
- 캡틴 제이슨 숫자 야구 기초
📌 미션에 들어가기 전 목표
- 클래스(객체)를 분리하는 연습
- 도메인 로직에 대한 단위 테스트를 작성
- 학습한 참고 자료
TDD 리팩토링 by 자바지기 박재성님
💰 로또 미션
- 로또 번호의 숫자 범위는 1~45까지이다.
- 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다.
- 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다.
- 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다.
- 1등: 6개 번호 일치 / 2,000,000,000원
- 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원
- 3등: 5개 번호 일치 / 1,500,000원
- 4등: 4개 번호 일치 / 50,000원
- 5등: 3개 번호 일치 / 5,000원
👀 주어진 요구 사항 정리
- 함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다.
- 함수(또는 메서드)가 한 가지 일만 잘 하도록 구현한다.
- else 예약어를 쓰지 않는다
-> return 하는 방식으로 구현하면 else를 사용하지 않아도 된다. - Java Enum을 적용한다.
- pickUniqueNumbersInRange()
✔ 기능 구현 목록 작성
- [x] 로또 구입 금액을 입력받는다. (한장당 1000원)
- [x] 한장당 1부터 45까지 서로 다른 6개의 임의의 수를 생성한다.
- [x] 1000원으로 나누어 떨어지지 않는경우 `IllegalArgumentException`를 발생시킨다.
- [x] 로또 번호는 오름차순으로 정렬한다.
- [x] 당첨 번호를 입력받는다.
- [x] 서로 다른 6개의 임의의 수를 입력한다.
- [x] 입력한 서로 다른 6개의 임의의 수는 오름차순으로 정렬한다.
- [x] 보너스 번호를 입력한다.
- [x] 일치하는 로또 번호와 당첨 금액을 정의하는 enum 클래스 생성
- [x] 사용자가 구매한 로또 번호와 당첨번호를 비교해 당첨 내역을 확인할 수 있다.
- [x] 일치하는 번호의 개수를 확인할 수 있다.
- [x] 일치하는 번호의 수만큼 수익이 측정된다.
- [x] 3개 번호가 일치하면 5_000원이며, 5등이다.
- [x] 4개 번호가 일치하면 50_000원이며, 4등이다.
- [x] 5개 번호가 일치하면 1_500_500원이며, 3등이다.
- [x] 5개 번호가 일치하고 보너스 번호가 일치하면 30_000_000원 2등이다.
- [x] 6개 번호가 일치하면 2_000_000_000원이다.
- [x] 사용자가 구입한 로또 금액과 당첨 금액으로 수익률을 확인할 수 있다.
- [x] 수익률은 소수점 둘재 자리에서 반올림한다.
💻 기능 구현
MVC 모델 적용기
lotto
controller
LottoController (domain과 View를 결정하여 전달)
domain
Lotto (당첨 로또 번호를 관리하는 역할)
LottoNumbers (1부터 45까지 서로 다른 6개의 임의의 수를 생성)
PlayerLottoAmount(사용자의 구입금액만큼 로또 구입)
Ranking (로또 번호와 당첨 금액을 정의하는 enum 클래스)
WinningResult (사용자와 당첨로또 번호를 비교하는 클래스)
view
ExceptionMessage(에러 메시지를 관리하는 클래스)
InputView (사용자 입력 클래스)
OutputView (출력 클래스)
Application(컨트롤러를 실행하는 클래스)
추가한 테스트코드
domain
LottoNumbersTest
-"로또_랜덤숫자_생성"
PlayerLottoAmountTest
-"올바르지_않은_금액"
-"구매한_로또_티켓_장수"
WinningResultTest
-"사용자가 구매한 로또 번호와 당첨번호를 비교해 등수 확인"
view
InputViewTest
-"올바르지 않은 입력값"
🎯 고민한 과정, 회고
- 제공된 Lotto 클래스는 리스트의 사이즈가 6이 아니라면 IllegalArgumentException을 발생시키는 함수가 주어져 있었다.
이를 내가 세운 기준(로또 넘버 리스트 예외사항을 확인하는)으로 함수들로 추가기능을 구현하고 다른 클래스들과 Lotto 클래스 역할을 분리하는 작업에 시간이 많이 투자되었다. - enum 은 연관성이 있는 상수를 묶어서 활용하는데
이는 DB에서 컬럼을 가져오는것과 같이 사용할 수 있는 것 같다고 생각했다.
그래서 다음과같이 1등이 가지는 맞힌 개수(6),상금,출력 모아서 활용했다.
FIRST(6, 2_000_000_000, "6개 일치 (2,000,000,000원) - "), // 1등
SECOND(5, 30_000_000, "5개 일치, 보너스 볼 일치 (30,000,000원) - "), // 2등
THIRD(5, 1_500_000, "5개 일치 (1,500,000원) - "), // 3등
FOURTH(4, 50_000, "4개 일치 (50,000원) - "), // 4등
FIFTH(3, 5_000, "3개 일치 (5,000원) - "), // 5등
MISS(0, 0, "");
- 객체의 상태 접근을 제한하는 과정이 기능과 테스트를 순차적으로 구현하는데 있어 초기값은 private 으로 구현하였지만 public과 같이 다른 접근제어자를 활용해야할 것 같은 생각이 들었다. 인스턴스 변수의 접근제어자를 세우는 내 기준을 정하는게 좋을 것 같다.
- TDD를 진행하는 과정에서 구현을 진행하고나니 테스트하기 어려운 코드들이 발생해서 시간을 많이 투자하였지만 테스트 코드를 완벽하게 작성하지 못한것에 아쉬움이 남는다.
- 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%)
총 수익률은 62.5%입니다.
총 수익률은 100,0%입니다.
총 수익률은 1,000,000,0%입니다.
위 예시와 같이 TEST 항목이 62.5%의 수익률을 나온다는 것을 확인하고 넘어갔지만 다시 확인해보니 수익률이 네자리이상은 가독성을 위해 ,를 찍어주었어야했는데 놓치고 말았다.
NumberFormat 함수를 사용하여 리팩토링을 진행해야할 것 같다.
사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고 "[ERROR]"로 시작하는 에러 메시지를 출력 후 종료하는 요구사항이 주어져 view의 아웃풋에서 관리하던 에러 출력 메시지들을 ExceptionMessage(클래스)로 관리하도록 리팩토링하였다.
🚩 다음 목표
- Java Enum 공부
-> 참고 자료 Java Enum 활용기 - getter를 사용하는 대신 객체에 메시지를 보내자
🐣 [구현 코드 보러가기]
https://github.com/COBI-98/java-lotto/tree/EUNSH1
'회고' 카테고리의 다른 글
[우테코] 프리코스 4주차 - 다리 건너기 회고록 (2) | 2023.01.01 |
---|---|
[우테코] 프리코스 2주차 - 숫자 야구 게임 회고록 (0) | 2023.01.01 |