-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
통합 테스트를 포함하고 컨트롤러를 리팩토링 #7
Changes from all commits
3d9dcae
620d197
60cb7de
35b56da
6fd1c50
798dd51
83a1377
ff16439
399d63e
1f14e7d
cba7969
554a306
df2957b
36f273a
cd23699
c9ad654
377490a
8d5f953
bfdca44
92c356f
0609483
bcbcf52
592a003
c0f09fc
afa5871
912243a
2015f02
f5ccb88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Layered Architecture에 따른 기능 목록 | ||
|
||
### Presentation Layer - 사용자와 상호작용 | ||
|
||
- UserInputManager - 사용자의 입력 | ||
- 로또 구입 금액 입력 | ||
- 당첨 번호 입력 | ||
- 보너스 번호 입력 | ||
- SystemOutputManager - 값 출력 | ||
- 로또 수량 및 번호 출력 | ||
- 당첨 내역 출력 | ||
- 수익률 출력 | ||
|
||
### Application Layer - 기능적 요구사항 | ||
|
||
- LottoGenerator - 금액에 따라 로또를 생성 | ||
- 구입 금액에 따른 로또 수량 계산 | ||
- 로또 수량에 따른 로또 번호 생성 | ||
|
||
- LottoResultCalculator - 로또 당첨 내역과 수익률 계산 | ||
- 로또의 당첨 내역와 수익률 계산 | ||
|
||
### Data Layer | ||
- Customer - class - **정확한** 고객의 저장 | ||
- 사용자 구입 금액 저장 | ||
- 생성한 로또 저장 | ||
- 로또 구입 금액 유효성 검사 | ||
- LottoCompany - class - **정확한** 당첨 번호와 보너스 번호 저장 | ||
- 당첨 번호 저장 | ||
- 보너스 번호 저장 | ||
- 당첨 번호와 보너스 번호 유효성 검사 | ||
- Lotto - record - **정확한** 로또 번호 저장 | ||
- 로또 저장 | ||
- 생성한 로또 유효성 검사 | ||
|
||
### Util | ||
|
||
- ExceptionStatus - enum | ||
- 예외 코드와 에러 메세지 저장 및 exception 발생 | ||
- Winnings - enum | ||
- 상금과 당첨 액수 저장 |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 파일을 함께 커밋한 이유가 무엇인가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프로그램 테스트나 실행하면서 자동으로 만들어졌나보네요 지우겠습니다! |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,23 @@ | ||
package lotto; | ||
|
||
import lotto.controller.LottoController; | ||
import lotto.model.service.LottoGenerator; | ||
import lotto.view.InputManager; | ||
import lotto.view.OutputManager; | ||
import lotto.view.SystemOutputManager; | ||
import lotto.view.UserInputManager; | ||
|
||
import java.util.Random; | ||
import java.util.Scanner; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
// TODO: 프로그램 구현 | ||
InputManager inputManager = new UserInputManager(new Scanner(System.in)); | ||
OutputManager outputManager = new SystemOutputManager(); | ||
Random random = new Random(); | ||
|
||
LottoController lottoController = new LottoController(inputManager, outputManager, random); | ||
lottoController.runGame(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package lotto.controller; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lotto.model.Lotto; | ||
import lotto.model.dto.Money; | ||
import lotto.model.service.LottoGenerator; | ||
import lotto.model.service.LottoResultCalculator; | ||
import lotto.model.dto.PrizeNumbers; | ||
import lotto.model.enums.Winnings; | ||
import lotto.view.InputManager; | ||
import lotto.view.OutputManager; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Random; | ||
import java.util.function.BiConsumer; | ||
import java.util.function.Consumer; | ||
|
||
@AllArgsConstructor | ||
public class LottoController { | ||
private final InputManager inputManager; | ||
private final OutputManager outputManager; | ||
private final Random random; | ||
// 입력 처리 및 비즈니스 로직 통제 | ||
public void runGame(){ | ||
LottoGenerator lottoGenerator = new LottoGenerator(random); | ||
LottoResultCalculator lottoResultCalculator = new LottoResultCalculator(); | ||
// 돈 받고 로또 생성 | ||
Money money = getMoney(Lotto::validateMoney); | ||
int lottoQuantity = lottoGenerator.countQuentityBasedOnMoney(money); | ||
outputManager.outputLottoQuantity(lottoQuantity); | ||
List<Lotto> lottos = lottoGenerator.createLottos(lottoQuantity); | ||
outputManager.outputLottoNumbers(lottos); | ||
|
||
PrizeNumbers prizeNumbers = getPrizeNumbersForLotto(); | ||
HashMap<Winnings,Integer> lottoResult = lottoResultCalculator.provideWinningDetails(lottos, prizeNumbers); | ||
outputManager.outputWinningDetails(lottoResult); | ||
String rateOrReturn = lottoResultCalculator.calculateReturn(lottoResult, money); | ||
outputManager.outputRateOfReturn(rateOrReturn); | ||
} | ||
|
||
// 로또를 사기 위한 구입 금액 입력 | ||
// 만약 자동차를 사기 위한 Money를 입력 받는 경우가 생긴다면? 어떻게 할 수 있을까? | ||
// 함수형 인터페이스의 익명함수를 사용하면 유효성 검사 로직과 입력 받는 로직을 분리할 수 있다. | ||
private Money getMoney(Consumer<Money> vaildator){ | ||
while(true){ | ||
try{ | ||
outputManager.displayMessage("구입금액을 입력해 주세요."); | ||
int amount = inputManager.enterPurchaseAmount(); // View | ||
Money money = new Money(amount); | ||
vaildator.accept(money); | ||
return money; // 데이터 생성 | ||
} | ||
catch(IllegalArgumentException e){ | ||
outputManager.displayMessage(e.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
private PrizeNumbers getPrizeNumbersForLotto(){ | ||
// (w) -> Lotto.validateLottoNumbers(w) | ||
List<Integer> winningNumbers = retryWinningNumbers(Lotto::validateLottoNumbers); | ||
int bonusNumber = retryBonusNumber(winningNumbers, Lotto::validateBonusNumber); | ||
return new PrizeNumbers(winningNumbers, bonusNumber); | ||
} | ||
|
||
// Lotto를 위한 당첨금 받기 | ||
private List<Integer> retryWinningNumbers(Consumer<List<Integer>> vaildator){ | ||
while(true){ | ||
try{ | ||
outputManager.displayWinningNumbersRequest(); | ||
List<Integer> winningNumbers = inputManager.enterWinningNumbers(); | ||
vaildator.accept(winningNumbers); | ||
return winningNumbers; | ||
} | ||
catch(IllegalArgumentException e){ | ||
outputManager.displayMessage(e.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
// Lotto를 위한 보너스 받기 | ||
private int retryBonusNumber(List<Integer> winningNumbers, BiConsumer<List<Integer>, Integer> vaildator){ | ||
while(true){ | ||
try{ | ||
outputManager.displayBonusNumberRequest(); | ||
int bonusNumber = inputManager.enterBonusNumber(); | ||
vaildator.accept(winningNumbers, bonusNumber); | ||
return bonusNumber; | ||
} | ||
catch(IllegalArgumentException e){ | ||
outputManager.displayMessage(e.getMessage()); | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 참고) SoC를 신경써서 확장 가능한 프로젝트 구조를 고안하고 있어요 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package lotto.model; | ||
|
||
import lotto.model.dto.Money; | ||
import lotto.model.enums.LottoDefinition; | ||
import lotto.model.enums.LottoExceptionStatus; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public record Lotto(List<Integer> numbers) { | ||
|
||
public Lotto(List<Integer> numbers) { | ||
Lotto.validateLottoNumbers(numbers); | ||
this.numbers = numbers.stream() // 정렬해서 저장 | ||
.sorted() | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Override | ||
public String toString(){ | ||
return numbers.toString(); | ||
} | ||
|
||
public static void validateMoney(Money money){ | ||
if (money.getMoney() % LottoDefinition.PriceOfLotto.getNumber() > 0) { | ||
throw new IllegalArgumentException(LottoExceptionStatus.IllegalPurchaseRemainderException.getMessage()); | ||
} | ||
} | ||
|
||
public static void validateBonusNumber(List<Integer> winningNumbers, int bonusNumber) { | ||
validateNumberLottoScope(bonusNumber); | ||
Lotto.validateNumberLottoScope(bonusNumber); // 유효 범위 | ||
if(winningNumbers.contains(bonusNumber)){ // 당첨 번호와 중복 체크 | ||
throw new IllegalArgumentException(LottoExceptionStatus.IllegalBonusDuplicateException.getMessage()); | ||
} | ||
} | ||
|
||
public static void validateLottoNumbers(List<Integer> numbers){ | ||
validateNumberCount(numbers); | ||
validateNumberDuplicate(numbers); | ||
validateNumbersLottoScope(numbers); | ||
} | ||
private static void validateNumberCount(List<Integer> numbers){ | ||
if (numbers.size() != LottoDefinition.SelectionSize.getNumber()) { | ||
throw new IllegalArgumentException(LottoExceptionStatus.IllegalLottoSizeException.getMessage()); | ||
} | ||
} | ||
private static void validateNumberDuplicate(List<Integer> numbers){ | ||
int distinctSize = (int) numbers.stream().distinct().count(); | ||
if(distinctSize != LottoDefinition.SelectionSize.getNumber()){ | ||
throw new IllegalArgumentException(LottoExceptionStatus.IllegalLottoDuplicateException.getMessage()); | ||
} | ||
} | ||
private static void validateNumberLottoScope(int number){ | ||
if(number>LottoDefinition.MaximumNumber.getNumber() || number<LottoDefinition.MinimunNumber.getNumber()){ | ||
throw new IllegalArgumentException(LottoExceptionStatus.IllegalLottoScopeException.getMessage()); | ||
} | ||
} | ||
private static void validateNumbersLottoScope(List<Integer> numbers){ | ||
numbers.forEach(Lotto::validateNumberLottoScope); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package lotto.model.dto; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class Money { | ||
private int money; | ||
public Money(int money){ | ||
validateMoney(money); | ||
this.money = money; | ||
} | ||
private void validateMoney(int money){ | ||
if(money < 0 ) | ||
// Lotto와는 관련 없는 에러 메시지기 때문에 따로 enum 처리하지 않음 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 우테코에서는 모든 상수를 Enum 처리하라고 가이드 하더라구요 별도의 파일로 분리하기 애매해서 그런거라면, 내부 Enum으로 처리해도 괜찮을 것 같아요 |
||
throw new IllegalArgumentException("[ERROR] 구입 금액은 0 이상일 때 입력할 수 있어요."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package lotto.model.dto; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
// 생성되고 더 이상 수정되지 않음 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
어떤 의도로 작성한 주석인가요? |
||
public record PrizeNumbers(List<Integer> winningNumbers, int bonusNumber){ | ||
|
||
public PrizeNumbers(List<Integer> winningNumbers, int bonusNumber){ | ||
this.winningNumbers = winningNumbers.stream() // 정렬해서 저장 | ||
.sorted() | ||
.collect(Collectors.toList()); | ||
this.bonusNumber = bonusNumber; | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MAXIMUM_NUMBER처럼 대문자와 언더바를 활용해서 명명하길 추천하고 있네요 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package lotto.model.enums; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public enum LottoDefinition { | ||
MaximumNumber(45), | ||
MinimunNumber(1), | ||
PriceOfLotto(1000), | ||
SelectionSize(6); | ||
|
||
private final int number; | ||
|
||
LottoDefinition(int number){ | ||
this.number = number; | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 접두사 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package lotto.model.enums; | ||
|
||
public enum LottoExceptionStatus { | ||
|
||
IllegalPurchaseRemainderException("[ERROR] 구입 금액은 1000으로 나눠 떨어질 때 입력할 수 있어요."), | ||
IllegalPurchaseNegativeException("[ERROR] 구입 금액은 0 이상일 때 입력할 수 있어요."), | ||
IllegalLottoDuplicateException("[ERROR] 로또 번호는 중복이 없을 때 입력할 수 있어요."), | ||
IllegalLottoSizeException("[ERROR] 로또 번호는 6개 숫자를 입력할 수 있어요."), | ||
IllegalLottoScopeException("[ERROR] 로또 번호는 1에서 45 사이 숫자를 입력할 수 있어요."), | ||
IllegalBonusDuplicateException("[ERROR] 보너스 번호는 당첨 보호와 중복이 없을 때 입력할 수 있어요."); | ||
|
||
private String message; | ||
|
||
LottoExceptionStatus(String message){ | ||
this.message = message; | ||
} | ||
public String getMessage(){ | ||
return message; | ||
} | ||
|
||
public IllegalArgumentException makeException(){ | ||
return new IllegalArgumentException(getMessage()); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package lotto.model.enums; | ||
|
||
import lombok.Getter; | ||
import java.util.Arrays; | ||
|
||
@Getter | ||
public enum Winnings { | ||
Fail(0,0,false), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Fifth(5000,3,false), | ||
Fourth(50000,4,false), | ||
Third(1500000,5,false), | ||
Second(30000000,5,true), | ||
First(2000000000,6,false); | ||
|
||
private int winningValue; | ||
private int winningMatchCount; | ||
private boolean bonusMatchCount; | ||
|
||
Winnings(int winningValue,int winningMatchCount, boolean bonusMatchCount) { | ||
this.winningValue = winningValue; | ||
this.winningMatchCount = winningMatchCount; | ||
this.bonusMatchCount = bonusMatchCount; | ||
} | ||
|
||
// valueOfWinningsAndBonus의 if문 분기를 제거. 대신 Fail에 따른 Output 로직 수정은 필요. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 솔이 이전에 if문 분기를 근거로 enum의 효용성을 얘기했을 때 조금 의아했어요 람다식으로 n번 순회하는 것보다, 이 생각에 대해서는 어떤 입장인지 궁금해요 |
||
public static Winnings of(int winningMatchCount, boolean bonusMatch){ | ||
return Arrays.stream(values()) | ||
.filter(it -> (it.winningMatchCount == winningMatchCount && | ||
it.bonusMatchCount == bonusMatch)) | ||
.findAny() | ||
.orElse(Fail); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Java 19에 대한 의존성을 만든 계기와 이유가 무엇인가요?
요구사항에서는 JDK 17에서의 테스트 성공을 명시해두었는데, 저희가 완전히 동일한 요구사항을 바탕으로 진행하고 있는 것이 아니므로 근거가 필요할 것 같습니다.