Open
Conversation
- 1,000원 단위 검증 - 0원 및 음수 금액 방지를 위한 검증 - 구매 가능한 로또 개수 계산 - IllegalArgumentException을 통한 도메인 예외 처리 - 위의 기능 단위 테스트 작성 - README.md 예외 처리 표에 Money 관련 예외 메시지 추가
- 로또 번호 개수(6개) 검증 - 로또 번호 범위(1~45) 검증 - 로또 번호 중복 검증 - 로또 번호 오름차순 자동 정렬 및 불변 리스트 저장 - IllegalArgumentException을 통한 도메인 예외 처리 - 위의 검증 및 기능 단위 테스트 작성 - README.md 예외 처리 표에 Lotto 관련 예외 메시지 추가
- Lotto를 활용해 당첨 번호 불변성(개수 6개, 1~45 범위, 중복 불가) 선행 검증 - 보너스 번호 범위(1~45) 및 당첨 번호와의 중복 검증 - 구매한 로또와의 일치 개수 조회 - 구매한 로또가 보너스 번호를 포함하는지 여부 확인 - [Lotto 확장] 생성자에서 null 방어 - [Lotto 확장] 번호 포함 여부 조회 - [Lotto 확장] 비교 대상 로또가 null일 때 예외 발생하도록 방어 - 로또 번호 목록을 불변 리스트로 노출하도록 변경해 캡슐화 강화 - WinningNumbersTest, LottoTest에 경계값/중복/null 검증 및 기능 단위 테스트 추가 - README.md 예외 처리 표에 Lotto/WinningNumbers 관련 예외 메시지 추가
- 1등부터 5등 및 꽝에 대한 등수 조건 정의 - 등수별 상금 제공 기능 - 일치 개수와 보너스 일치 여부 기반 등수 판정 로직 구현 - 등수 판정 및 상금 제공 기능에 대한 단위 테스트 - 보너스 번호가 등수에 미치는 영향 범위 검증
- 구매한 로또 목록과 당첨 번호를 기반으로 등수별 당첨 개수 집계 - 등수별 상금을 누적해 총 당첨 금액 계산 - 구입 금액을 인자로 받아 수익률(총 당첨금 / 구입 금액) 계산 - 로또 목록 및 각 원소, 당첨 번호에 대한 null 방어 로직과 예외 메시지 정의 - 검증 및 총 당첨금 집계, 수익률 조회 기능 관련 단위 테스트 작성 - README.md 예외 처리 표에 LottoResults 관련 예외 메시지 추가
- 로또 생성 로직을 LottoGenerator 인터페이스로 추상화 - Randoms 유틸을 사용하는 RandomLottoGenerator 구현 - LottoFactory가 LottoGenerator에 의존하도록 수정 (DIP) - LottoFactory의 생성 개수(count) 유효성 검증 - 테스트 더블 FakeLottoGenerator 구현 - FakeLottoGenerator를 사용한 LottoFactory 단위 테스트 작성 - LottoGenerator 인터페이스의 구현 클래스 관련 단위 테스트 작성 - README.md 예외 처리 표에 LottoGenerator, LottoFactory 관련 예외 메시지 추가 - README.md 시퀀스 다이어그램 및 객체 역할 요약 추가
- InputView: 구입 금액, 당첨 번호, 보너스 번호 입력 기능 구현 - OutputView: 구매 로또, 당첨 통계, 수익률, 에러 메시지 출력 기능 구현 - InputValidator: View로부터 받은 입력의 형식(공백, 숫자) 검증 로직 분리 - InputValidator 관련 단위 테스트 작성 - README.md 예외 처리 표에 InputValidator 관련 예외 메시지 추가
- LottoController에서 구입 금액 입력 → 로또 생성 → 당첨 번호 입력 → 결과 집계 → 수익률 출력까지 전체 시나리오 제어 - 잘못된 입력, 금액, 당첨 번호, 보너스 번호에 대해 예외 메시지 출력 후 재입력 받도록 반복 처리 - Money 값을 활용해 구매 가능 로또 수 계산 및 수익률 계산 시 구입 금액 전달 - Application main에서 LottoFactory, RandomLottoGenerator, LottoController를 조립해 프로그램 실행 진입점 구성
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎰 로또 게임 (Lotto Game)
사용자가 입력한 금액만큼 로또를 자동으로 발행하고, 당첨 번호와 보너스 번호를 기준으로 결과 통계와 수익률을 출력하는 콘솔 기반 프로그램입니다.
Java 21 환경에서 동작하며, 기능별 책임을 분리해 구현하는 데 중점을 두었습니다.
🍭 🎯 프로젝트의 지향점 및 방향
관련된 데이터와 동작을 함께 묶어 각 클래스가 분명한 책임을 갖도록 구성하고, 여러 객체들이 역할에 따라 협력하며 하나의 기능을 완성할 수 있도록 설계합니다.
TDD 사이클 중 Inside-Out 방식을 기반으로, 입출력보다는 먼저 도메인 로직을 중심으로 개발을 시작하고, 테스트 가능한 작은 단위부터 점차 확장해 나갑니다.
🔁 시퀀스 다이어그램
애플리케이션의 전체 동작 과정과 객체 간의 상호작용을 시각화하기 위해 시퀀스 다이어그램을 사용했습니다.
sequenceDiagram participant U as 사용자 participant I as InputView participant O as OutputView participant C as LottoController participant M as Money participant F as LottoFactory participant G as LottoGenerator participant L as Lotto participant W as WinningNumbers participant R as LottoResults Note over U,C: 🎫 1단계: 로또 구매 loop 유효한 금액이 입력될 때까지 U->>I: 구입 금액 입력 I->>C: 금액 전달 C->>M: Money 생성 및 검증 alt 검증 성공 M-->>C: 유효한 Money 객체 else 검증 실패 M-->>C: IllegalArgumentException C->>O: 에러 메시지 출력 O->>U: 에러 표시 end end C->>M: getLottoCount() 호출 M-->>C: 구매 가능한 로또 개수(count) C->>F: generate(count) 호출 F->>G: generate(count) 위임 loop count번 G->>G: Randoms.pickUniqueNumbersInRange(1,45,6) G->>L: Lotto(numbers) 생성 end G-->>F: List<Lotto> 반환 F-->>C: List<Lotto> 반환 C->>O: 구매한 로또 목록 출력 O->>U: 로또 목록 표시 Note over U,C: 🏆 2단계: 당첨 번호 입력 loop 유효한 당첨 번호가 입력될 때까지 U->>I: 당첨 번호 입력 (쉼표 구분) I->>C: 당첨 번호 전달 C->>W: WinningNumbers 생성 및 검증 alt 검증 성공 W-->>C: 당첨 번호 객체 생성됨 else 검증 실패 W-->>C: IllegalArgumentException C->>O: 에러 메시지 출력 O->>U: 에러 표시 end end loop 유효한 보너스 번호가 입력될 때까지 U->>I: 보너스 번호 입력 I->>C: 보너스 번호 전달 C->>W: 보너스 번호 설정 및 검증 alt 검증 성공 W-->>C: 최종 당첨 번호 객체 완성 else 검증 실패 W-->>C: IllegalArgumentException C->>O: 에러 메시지 출력 O->>U: 에러 표시 end end Note over U,C: 📊 3단계: 결과 분석 및 출력 C->>R: LottoResults 생성 (List<Lotto>, WinningNumbers) loop 각 로또에 대해 R->>R: 등수별 카운트 증가 R->>R: 총 상금 누적 end C->>R: calculateYield(구입 금액) 호출 R-->>C: 수익률 반환 C->>O: 당첨 통계 출력 O->>U: 통계 표시 C->>O: 수익률 출력 O->>U: 수익률 표시🧱 객체 역할 요약
MoneyLottoLottoGeneratorLotto리스트 생성RandomLottoGeneratorRandoms.pickUniqueNumbersInRange()를 사용해 번호 생성,Lotto객체 생성LottoFactoryLottoGenerator)에 생성 요청을 위임하는 팩토리LottoGenerator구현체WinningNumbersLottoRankLottoResultsInputViewConsole.readLine()사용OutputViewInputValidatorLottoController🚰 구현 순서 (Inside-Out 방식)
1단계: 핵심 도메인 모델 구현
Money: 금액을 표현하고, 1,000원 단위 검증 및 로또 구매 가능 개수 계산 책임을 가집니다.Lotto: 로또 한 장(6개 번호)을 표현하며, 번호 개수, 범위, 중복 등 규칙의 불변성을 보장합니다.2단계: 당첨 규칙 및 판정 로직 구현
WinningNumbers: 당첨 번호(6개)와 보너스 번호(1개)를 가지며, 관련된 유효성 검증 책임을 가집니다.LottoRank: 5개 등수와 '꽝'에 대한 조건(일치 개수, 보너스 여부)과 상금을enum으로 정의합니다. (등수 판정 로직 포함)3단계: 결과 집계 및 분석 로직 구현
LottoResults: 구매한 모든Lotto와WinningNumbers를 비교하여, 등수별 당첨 횟수를 집계하고 최종 수익률을 계산합니다.4단계: 로또 생성 로직 구현
LottoFactory:LottoGenerator를 사용해 규칙에 맞는 로또 목록을 생성합니다.5단계: 입출력(UI) 계층 구현
InputView: 사용자로부터 구입 금액, 당첨 번호, 보너스 번호를 입력받는 책임을 가집니다.OutputView: 구매 내역, 당첨 통계, 수익률, 에러 메시지 등 모든 출력 내용을 형식에 맞게 보여주는 책임을 가집니다.InputValidator:InputView를 통해 들어온 사용자 입력 값의 형식(숫자인지, 쉼표로 구분되는지 등)을 검증합니다.6단계: 애플리케이션 통합 및 실행
LottoController: 전체 애플리케이션의 실행 흐름(로또 구매 → 당첨 번호 입력 → 결과 발표)을 제어하고, 예외 발생 시 재입력 로직을 처리합니다.Application: 프로그램의 시작점(main메서드)으로,LottoController를 생성하고 실행합니다.7단계: 리팩토링 및 최종 검토
ValidationUtil,Retry등 중복 로직을 유틸리티 클래스로 추출합니다.📋 예외 처리
사용자의 입력 오류로 예외가 발생하면
[ERROR] ...로 시작하는 에러 메시지를 사용자에게 출력하고 해당 입력부터 다시 입력을 진행할 수 있도록 합니다.[ERROR] 당첨 결과를 계산할 로또 목록은 null일 수 없습니다.[ERROR] 로또 목록에 null이 포함될 수 없습니다.[ERROR] 당첨 번호는 null일 수 없습니다.[ERROR] 구입 금액은 0보다 커야 합니다.[ERROR] 구입 금액은 0보다 커야 합니다.[ERROR] 1,000원 단위로 입력해 주세요.[ERROR] 로또 번호는 null일 수 없습니다.[ERROR] 비교할 로또가 null일 수 없습니다.[ERROR] 로또 번호는 6개여야 합니다.[ERROR] 로또 번호는 중복될 수 없습니다.[ERROR] 로또 번호는 1부터 45 사이여야 합니다.[ERROR] 보너스 번호는 1부터 45 사이여야 합니다.[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다.[ERROR] 로또 생성기는 null일 수 없습니다.[ERROR] 로또 생성 개수는 1개 이상이어야 합니다.[ERROR] 입력은 비어 있을 수 없습니다.[ERROR] 구입 금액은 숫자여야 합니다.[ERROR] 당첨 번호는 숫자여야 합니다.[ERROR] 보너스 번호는 숫자여야 합니다.⚙️ 개발 및 기술 제약
Application클래스의main()메서드여야 한다.build.gradle파일은 수정할 수 없다. 외부 라이브러리를 추가하지 않는다.camp.nextstep.edu.missionutils.Randoms.pickUniqueNumbersInRange(1, 45, 6)을 사용한다.camp.nextstep.edu.missionutils.Console.readLine()으로만 받는다.System.exit()를 호출해서는 안 된다.else문,switch/case, 삼항 연산자는 사용하지 않는다.Lotto클래스에는 필드를 추가하지 않는다.📝 구현 기록 / 고민 정보
구현 과정에서 배우고 고민했던 것들을 기록하는 공간입니다.