- 로또 요구사항을 파악한다.
- 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.
- 코드 리뷰 피드백에 대한 개선 작업을 하고 다시 PUSH한다.
- 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.
- 이번 미션의 핵심은 내가 구현하는 코드에 단위 테스트를 추가하는 경험을 하는 것이다.
- 모든 예외 상황을 처리하기 위해 너무 복잡하게 접근하지 않아도 된다.
- 사용자가 입력한 문자열 값에 따라 사칙연산을 수행할 수 있는 계산기를 구현해야 한다.
- 입력 문자열의 숫자와 사칙 연산 사이에는 반드시 빈 공백 문자열이 있다고 가정한다.
- 나눗셈떨어지는 값으로 한정한다.
- 문자열 계산기는 사칙연산의 계산 우선순위가 아닌 입력 값에 따라 계산 순서가 결정된다. 즉, 수학에서는 곱셈, 나눗셈이 덧셈, 뺄셈 보다 먼저 계산해야 하지만 이를 무시한다.
- 예를 들어 2 + 3 * 4 / 2와 같은 문자열을 입력할 경우 2 + 3 * 4 / 2 실행 결과인 10을 출력해야 한다.
- 사용자에게 숫자와 사칙 연산 문자열을 입력받는다.
- 입력 문자열은 숫자, 사칙 연산, 공백만 입력한다.
- 계산기에 문자열을 전달하면, 사칙 연산의 결과를 반환한다.
- 계산기에 전달된 문자열을 공백으로 나누면 홀수 개이며, 홀수번째는 숫자가, 짝수번째는 사칙 연산이어야한다.
- 계산기에 전달된 문자열의 사칙연산은 +, -, *, /만 가능하다.
- 계산기에 전달된 문자열의 나눗셈 수는 결과 값을 정수로 떨어지는 값으로 한정한다.
- 계산기는 사칙연산의 계산 우선순위가 아닌 입력 값에 따라 계산 순서가 결정된다.
- 사용자에게 결과 값을 출력한다.
- indent(들여쓰기) depth를 2단계에서 1단계로 줄여라.
- depth의 경우 if문을 사용하는 경우 1단계의 depth가 증가한다. if문 안에 while문을 사용한다면 depth가 2단계가 된다.
- 메소드의 크기가 최대 10라인을 넘지 않도록 구현한다.
- method가 한 가지 일만 하도록 최대한 작게 만들어라.
- else를 사용하지 마라.
- 연산자에 따른 연산을 Enum 등을 활용해 보시는 것도 좋을 것 같습니다
- 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다.
- 로또 1장의 가격은 1000원이다.
구입금액을 입력해 주세요.
14000
14개를 구매했습니다.
[8, 21, 23, 41, 42, 43]
[3, 5, 11, 16, 32, 38]
[7, 11, 16, 35, 36, 44]
[1, 8, 11, 31, 41, 42]
[13, 14, 16, 38, 42, 45]
[7, 11, 30, 40, 42, 43]
[2, 13, 22, 32, 38, 45]
[23, 25, 33, 36, 39, 41]
[1, 3, 5, 14, 22, 45]
[5, 9, 38, 41, 43, 44]
[2, 8, 9, 18, 19, 21]
[13, 14, 18, 21, 23, 35]
[17, 21, 29, 37, 42, 45]
[3, 8, 27, 30, 35, 44]
지난 주 당첨 번호를 입력해 주세요.
1, 2, 3, 4, 5, 6
당첨 통계
---------
3개 일치 (5000원)- 1개
4개 일치 (50000원)- 0개
5개 일치 (1500000원)- 0개
6개 일치 (2000000000원)- 0개
총 수익률은 0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
- 로또 티켓은 랜덤한 숫자 6개를 반환한다.
- 로또 티켓은 1과 45사이의 숫자 6개로 구성된다.
- 로또 티켓은 중복된 숫자를 가지지 않는다.
- 로또 발행 머신은 1장의 가격(1000원)을 넣으면 1장이 발급된다.
- 로또 머신은 구입 금액에 해당하는 로또 티켓 N장을 발급해야 한다.
- 로또 머신은 구입 금액을 장당 가격으로 나누었을 때, 정수가 아니면 에러를 반환한다.
- 로또 머신은 지난주 당첨번호를 입력하면 N개의 번호가 일치하는 티켓 개수와 상금을 각각 반환한다.
- 로또 머신은 총수익률을 반환한다.
- 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외
- 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.
- UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
- 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다.
- 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
- 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
- else 예약어를 쓰지 않는다.
- 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
- else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
- 기능을 구현하기 전에 README.md 파일에 구현할 기능 목록을 정리해 추가한다.
- git의 commit 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다.
- 테스트 케이스 실패 확인이 필요할 것 같습니다 😄
- LottoMachine이 하고 있는일이 너무 많습니다 😅 LottoMachine 로또구매금액을 관리하는 객체가 하나 정의되면 어떨까요😄 (예를 들어 PucharseAmount 같은??)
- LottoTicket도 하고 있는 역할이 좀 많은 것 같습니다 😄 로또 번호 객체가 하나 정의되면 어떨까요??
- LottoTicket의 로또 번호는 변하지 않는 값(1~45)이므로 사전에 정의를 하고 그 안에서 6개를 랜덤으로 가져오게 하는 방식이 성능면에서도 더 좋을 것 같습니다 🙏 힌트를 활용해보시는 것도 좋을 것 같아요 🙇
- 로또 자동 생성은 Collections.shuffle() 메소드 활용한다.
- Collections.sort() 메소드를 활용해 정렬 가능하다.
- OutputView에서 LottoRank에 계속 수정이 발생할 것 같습니다. LottoRank라는 Enum잘 정의해주셨으니 순회하는 식으로 변경하면 될 것 같네요 😄
- LottoRank에서 금액을 표현할 때 가독성을 위해 2_000_000_000 으로도 표현 가능합니다 🙇
- LottoNumber라는 원시객체가 getAllNumbers를 해서 자기의 객체 그룹을 반환하는게 좀 어색하긴 합니다 😄
- 로또 구매금액이니까 PurchaseAmount가 관리하게 되면 getTicketCount에 인자로 전달될 필요도 없고 이미 검증도 PurchaseAmount가 하고 있습니다 😄
- LottoTickets의 cost, return rate도 PurchaseAmount로 위임해보면 어떨까요??
- LottoNumber가 1 ~ 45가 아닐 때 제대로 검증되는지도 테스트 되면 좋을 것 같네요 😄
- 정렬이 한번 되면 좋을 것 같습니다 😄
- 2등을 위해 추가 번호를 하나 더 추첨한다.
- 당첨 통계에 2등도 추가해야 한다.
[... 생략 ...]
지난 주 당첨 번호를 입력해 주세요.
1, 2, 3, 4, 5, 6
보너스 볼을 입력해 주세요.
7
당첨 통계
---------
3개 일치 (5000원)- 1개
4개 일치 (50000원)- 0개
5개 일치 (1500000원)- 0개
5개 일치, 보너스 볼 일치(30000000원) - 0개
6개 일치 (2000000000원)- 0개
총 수익률은 0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
- 로또 발행 머신은 당첨 통계를 계산할 때, 지난 주 당첨 번호와 보너스 볼을 입력 받는다.
- 로또 등수에 '5개 일치, 보너스 볼 일치(30_000_000)'를 추가한다.
- 로또 당첨 통계를 계산할 때, 5개 일치하는 로또 티켓이 보너스 볼 번호를 가지는지 확인하여 등수를 조정한다.
- 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외
- java enum을 적용해 프로그래밍을 구현한다.
- 규칙 8: 일급 콜렉션을 쓴다.
- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
- 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
- else 예약어를 쓰지 않는다.
- 로또 넘버의 범위(1~45)가 LottoNumber와 LottoMachine 두 군데에서 쓰일 경우
- LottoNumber에 값을 private -> public으로 변경해서 사용한다거나
- 상수만 가진 클래스를 정의해서 사용하게 한다거나
- 설정파일로 관리한다거나 하는 식의 방법이 있을 것 같네요 😄
- 소소한 의견이지만 bonusCount가 1, 0의 구분이라면 boolean형으로 표현했어도 괜찮았을 것 같습니다 🙏
- 당첨번호와 보너스볼이 하나의 객체로 관리되는것도 나쁘지 않을 것 같습니다 😄 이 부분은 추가 검증이 필요할 것 같아요 🙏
- LottoTicket의 rank를 WinningLotto쪽으로 위임하면 순환을 벗어날 수 있을 것 같습니다 🙇
- WinningLotto에 검증을 위임하면 될 것 같습니다 🙇 (당첨번호와 보너스 볼은 중복되면 안됨.)
- 현재 로또 생성기는 자동 생성 기능만 제공한다. 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다.
- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다.
구입금액을 입력해 주세요.
14000
수동으로 구매할 로또 수를 입력해 주세요.
3
수동으로 구매할 번호를 입력해 주세요.
8, 21, 23, 41, 42, 43
3, 5, 11, 16, 32, 38
7, 11, 16, 35, 36, 44
수동으로 3장, 자동으로 11개를 구매했습니다.
[8, 21, 23, 41, 42, 43]
[3, 5, 11, 16, 32, 38]
[7, 11, 16, 35, 36, 44]
[1, 8, 11, 31, 41, 42]
[13, 14, 16, 38, 42, 45]
[7, 11, 30, 40, 42, 43]
[2, 13, 22, 32, 38, 45]
[23, 25, 33, 36, 39, 41]
[1, 3, 5, 14, 22, 45]
[5, 9, 38, 41, 43, 44]
[2, 8, 9, 18, 19, 21]
[13, 14, 18, 21, 23, 35]
[17, 21, 29, 37, 42, 45]
[3, 8, 27, 30, 35, 44]
지난 주 당첨 번호를 입력해 주세요.
1, 2, 3, 4, 5, 6
보너스 볼을 입력해 주세요.
7
당첨 통계
---------
3개 일치 (5000원)- 1개
4개 일치 (50000원)- 0개
5개 일치 (1500000원)- 0개
5개 일치, 보너스 볼 일치(30000000원) - 0개
6개 일치 (2000000000원)- 0개
총 수익률은 0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)
- 로또 머신에 구입 금액, 수동으로 구매할 로또 번호를 전달한다.
- 로또 머신은 구입 금액이 수동으로 구매할 로또 수보다 많은지 검증한다.
- 로또 머신은 수동으로 구매할 로또 수를 제외하고 나머지를 자동으로 발행한다.
- 로또 머신은 자동으로 구매한 로또 수와 수동으로 구매한 로또 수를 알려준다.
- 규칙 3: 모든 원시값과 문자열을 포장한다.
- 로또 숫자 하나는 int 타입이다. 이 숫자 하나를 추상화한 LottoNo 객체를 추가해 구현한다.
- 규칙 5: 줄여쓰지 않는다(축약 금지).
- 예외 처리를 통해 에러가 발생하지 않도록 한다.
- 사용자가 잘못된 값을 입력했을 때 java exception으로 에러 처리를 한다.
- java8에 추가된 Optional을 적용해 NullPointerException이 발생하지 않도록 한다.