-
Notifications
You must be signed in to change notification settings - Fork 3
민형 로또(수동) 구현 #12
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
base: master
Are you sure you want to change the base?
민형 로또(수동) 구현 #12
Conversation
| private static final int LOTTO_PRICE = 1000; | ||
| private final int purchaseAmount; | ||
| private final int numberOfTicket; |
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.
돈이 로또가격과 티켓의 개수를 가지고있는게 어색해보여
이건 LottoMachine 쪽에 있는게 나은거같아
|
|
||
| OutputView.printLottoTickets(lottoTickets); | ||
|
|
||
| List<Integer> winningNumbers = InputView.inputLastWinningNumbers(); |
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.
WinningNumbers는 일급컬렉션으로 묶는게 좋아보여
그럼 LottoNumberGenerator에 있는 public static LottoNumber findByNumber(int number) 메소드가 없어도 될거같아.
| public enum WinningSheet { | ||
| FAIL(0, 0), | ||
| FOURTH(3, 5000), | ||
| THIRD(4, 50000), | ||
| SECOND(5, 1500000), | ||
| FIRST(6, 2000000000); | ||
|
|
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.
로또 보너스 번호가 없는거같아!
|
|
||
| OutputView.printNumberOfTicket(lottoMoney); | ||
|
|
||
| List<LottoTicket> lottoTickets = LottoMachine.purchaseLottoTicket(lottoMoney); |
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.
List은 일급컬렉션으로 묶는게 좋아보여!
| static { | ||
| lottoNumbers = IntStream.rangeClosed(LOTTO_NUMBER_UNDER_BOUND, LOTTO_NUMBER_UPPER_BOUND) | ||
| .mapToObj(LottoNumber::new) | ||
| .collect(Collectors.toList()); | ||
| } |
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.
싱글턴!!
내 개인적인 생각인데 Interger 클래스 까보면 내부에 static class 로 IntergerCache가 있단말이야?
그래서 LottoNumber도 LottoCache같은 거를 내부에 static class로 들고 있고
로또 넘버를 생성하는 거를 부르면 LottoCache에서 미리 생성된 싱글턴들을 반환해 주는건 어떨까??
LottoNumber의 생성자가 열려있어서 싱글턴하게 사용되지 않을수 있을거 같은 생각이 들어서!
LottoNumber의 생성자는 private으로 닫아두고 해당 private 생성자를 이용해서 static class에 cache를 생성해두고
of 같은 정적 팩토리 메서드로 캐싱된 값을 가져올수 있게 하는거지!
| public static List<LottoTicket> purchaseLottoTicket(LottoMoney lottoMoney) { | ||
| List<LottoTicket> lottoTickets = new ArrayList<>(); | ||
|
|
||
| for (int i = 0; i < lottoMoney.getNumberOfTicket(); i++) { | ||
| List<LottoNumber> lottoNumbers = LottoNumberGenerator.generateLottoNumbers(); | ||
| lottoTickets.add(new LottoTicket(lottoNumbers)); | ||
| } | ||
|
|
||
| return lottoTickets; | ||
| } |
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.
LottoTicket이 노출될 필요가 있나? 라는 생각이 들었어!
LottoNumberGenrator가 굳이 List<LottoNumber>를 줘야하나? 라는 생각에서
LottoTicket을 반환해 줘도 문제 없지 않을까? 라는 생각이 들어
| public static List<LottoNumber> generateLottoNumbers() { | ||
| Collections.shuffle(lottoNumbers); |
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.
Collections.shuffle(lottoNumbers); 라는 부분은 우리가 제어할수 없는 부분이잖아?
제어할 수 없는 부분에 대한 의존성은 분리해 놓는게 좋지 않을까?
| private Map<WinningSheet, Long> makeWinningStatistics(List<Integer> drawResults) { | ||
| Map<WinningSheet, Long> winningStatistics = new LinkedHashMap<>(); | ||
|
|
||
| for (WinningSheet winningSheet : WinningSheet.values()) { | ||
| long count = drawResults.stream() | ||
| .filter(drawResult -> winningSheet.getMatchCount() == drawResult) | ||
| .count(); | ||
|
|
||
| winningStatistics.put(winningSheet, count); | ||
| } | ||
|
|
||
| return winningStatistics; | ||
| } |
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.
이 부분은 winningSheet에게 책임을 더 넘겨보는건 어떨까?
long count = drawResults.stream()
.filter(drawResult -> winningSheet.getMatchCount() == drawResult)
.count();특히 이 부분..!!
| .reduce(Integer::sum) | ||
| .orElse(0); | ||
|
|
||
| double rateOfReturn = profit / lottoMoney.getPurchaseAmount(); |
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.
이 부분도 LottoMoney가 해줄수 있지 않을까?
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class DrawingMachine { |
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.
우승 번호의 일급컬렉션 역할이라 위 이름이 그다지 어울리지 않는것 같아!
| private void validateDuplicateWinningNumbers(List<Integer> winningNumbers) { | ||
| Set<Integer> nonDuplicateNumbers = new HashSet<>(winningNumbers); | ||
|
|
||
| if (nonDuplicateNumbers.size() != WINNING_NUMBER_SIZE) { |
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.
nonDuplicateNumbers.size() 가 7이어도 이 메서드는 실패하는 건데 중복은 아닌거잖아?
validateWinningNumbersSize 메서드가 먼저 호출되서 지금은 검증이 되겠지만
엄연히 validateDuplicateWinningNumbers 메서드만 호출했을때는 잘못된 로직아닐까?
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| public class LottoResult { |
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.
이 객체에서 객체간의 의존성을 더 잘게 쪼개고 책임을 분리해보는게 좋을것 같아
pci2676
left a comment
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.
오~~~ 전체적으로 깔끔하게 구현된 것 같아
| public LottoMoney(int purchaseAmount) { | ||
| validatePurchaseAmount(purchaseAmount); | ||
| this.numberOfAutoTicket = purchaseAmount / LOTTO_PRICE; | ||
| } |
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.
사용되지 않는 생성자네!
| public static LottoTicket ofFixed(List<Integer> numbers) { | ||
| validateSize(numbers); | ||
| return new LottoTicket(LottoNumberGenerator.generateFixedNumber(numbers)); | ||
| } | ||
|
|
||
| public static LottoTicket ofAuto() { | ||
| return new LottoTicket(LottoNumberGenerator.generateRandomNumber(LOTTO_NUMBERS_SIZE)); | ||
| } |
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.
LottoNumberGenerator의 의존성이 LottoTicket 내부에 숨겨져있어서 테스트하기가 힘들것 같아
fixed 티켓은 테스트할수 있지만 auto 티켓은 이 상태로는 테스트하기가 힘들것 같아보여
| public LottoTicket getWinningTicket() { | ||
| return winningTicket; | ||
| } | ||
|
|
||
| public LottoNumber getBonusNumber() { | ||
| return bonusNumber; | ||
| } |
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.
사용되지 않는 메서드넹
| if (isThirdAndMatchBonus(findSheet, matchBonus)) { | ||
| return SECOND; | ||
| } |
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.
| if (isThirdAndMatchBonus(findSheet, matchBonus)) { | |
| return SECOND; | |
| } | |
| if (findSheet.isSecond(matchBonus)) { | |
| return SECOND; | |
| } |
이건 어때?
| public double calculateRateOfReturn(int profit) { | ||
| int purchaseAmount = (numberOfAutoTicket + numberOfManualTicket) * LOTTO_PRICE; | ||
|
|
||
| return profit / purchaseAmount; | ||
| } |
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.
int 결과 계산이 double이 되어버렸어
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class LottoBill { |
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.
난 갠적으로 LottoTickets가 더 이름이 나은거같아보여
| this.lottoTickets = lottoTickets; | ||
| } | ||
|
|
||
| public LottoResult drawAllLotto(LottoWinningTicket lottoWinningTicket) { |
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.
draw의 뜻이 끌어당기다, 그리다 이런뜻으로 알고있는데 다른 뜻은 모르겠어서
어떤 일을 하는지 이름만 보고는 잘 모를거같아
…) -> matchAllLotto() 로 이름 변경
refactor(LottoNumberGenerator): generateRandomNumber가 인자로 NumberGenerator 를 받아서 호출하도록 변경 refactor(LottoTicket): ofAuto() 메소드 인자로 NumberGenerator 구현체를 받도록 변경
| import java.util.List; | ||
|
|
||
| public interface NumberGenerator { | ||
| List<Integer> generate(int min, int max); |
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.
음 나라면
| List<Integer> generate(int min, int max); | |
| List<Integer> generateRangeOf(int min, int max); |
라고 했을거같아
| public static LottoTicket ofFixed(List<Integer> numbers) { | ||
| validateSize(numbers); | ||
| return new LottoTicket(LottoNumberGenerator.generateFixedNumber(numbers)); | ||
| } | ||
|
|
||
| public static LottoTicket ofAuto(NumberGenerator numberGenerator) { | ||
| return new LottoTicket(LottoNumberGenerator.generateRandomNumber(LOTTO_NUMBERS_SIZE, numberGenerator)); | ||
| } | ||
|
|
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.
티켓 자체가 수동or자동 티켓을 발급해주는게 난조금 이상하게 보여
티켓이 티켓을 생성하는 책임을 가지고있다는 느낌이랄까?
흠.. 솔직히 잘 모르겠다 나는 LottoTicket을 만들어주는 애는 다른 클래스에 책임을 넘겼어.
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.
음 이건 정적 펙토리 메서드입니다.
객체의 생성은 해당 객체의 생성자로만 이루어지는데, 생성자의 이름변경을 못하니 클래스메서드로 생성함수의 이름으로 명확하게 표현한걸로 보이네요,
이런 구현은 좋아보입니다.
| Set<Integer> duplicateNumbers = lottoNumbers.stream() | ||
| .map(LottoNumber::getNumber) | ||
| .collect(Collectors.toSet()); |
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.
결과를 Set으로 안받구 그냥 integer로 받아도 좋을듯!
| Set<Integer> duplicateNumbers = lottoNumbers.stream() | |
| .map(LottoNumber::getNumber) | |
| .collect(Collectors.toSet()); | |
| int distinctNumberSize = lottoNumbers.stream() | |
| .map(LottoNumber::getNumber) | |
| .collect(Collectors.toSet()) | |
| .size() |
|
|
||
| public int findMatchCount(LottoTicket winningTicket) { | ||
| return (int) IntStream.range(0, LOTTO_NUMBERS_SIZE) | ||
| .filter(index -> winningTicket.findByIndex(index).equals(this.findByIndex(index))) |
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.
디미터 법칙을 위반하고 있는것 같아!
| public class LottoMoney { | ||
| private static final int LOTTO_PRICE = 1000; | ||
| private int numberOfAutoTicket; | ||
| private int numberOfManualTicket; |
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.
흠 Money는 딱 돈에 대한 값만을 들고 있을것 같은 VO의 네이밍인데 산 갯수 두개를 들고 있는게 뭔가 어색해보여 이름을 바꿔줘도 될것같아.
아니면 객체를 나눠서 돈은 돈대로 갯수는 갯수대로 따로 관리해도 좋을것 같아
그리고 VO니까 final을 붙여줘도 좋을것 같아
| } | ||
| } | ||
|
|
||
| public int findMatchCount(LottoTicket winningTicket) { |
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.
for문을 index에 의존해서 돌리는 방법이 아니라
애초에 LottNumber와 index를 감싸는 객체를 만들어 클래스를 만들어서 비교하면 더 깔끔하게 로직을 짤 수 있을거같아.
class PickedLottoNumber{
private int order;
private LottoNumber lottoNumber;
.....
}| public static void main(String[] args) { | ||
| int purchaseAmount = InputView.inputPurchaseAmount(); | ||
|
|
||
| int numberOfManualTicket = InputView.inputNumberOfManualTicket(); |
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.
InputView에서 LottoMoney객체를 한번에 받아 가져오는게 좋을듯, 기본 타입을 굳이 다 노출시킬필요도 없고 도메인 객체를 input에서 받아도 상관없어보여
LottoMoney lottoMoney=InputView.inputLottoInfo();
|
|
||
| int bonusNumber = InputView.inputBonusNumber(); | ||
|
|
||
| LottoWinningTicket lottoWinningTicket = new LottoWinningTicket(winningNumbers, bonusNumber); |
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.
이것도 위와 마찬가지로 View에서 바로 받아와도 문제없어
| public static LottoTicket ofFixed(List<Integer> numbers) { | ||
| validateSize(numbers); | ||
| return new LottoTicket(LottoNumberGenerator.generateFixedNumber(numbers)); | ||
| } | ||
|
|
||
| public static LottoTicket ofAuto(NumberGenerator numberGenerator) { | ||
| return new LottoTicket(LottoNumberGenerator.generateRandomNumber(LOTTO_NUMBERS_SIZE, numberGenerator)); | ||
| } | ||
|
|
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.
음 이건 정적 펙토리 메서드입니다.
객체의 생성은 해당 객체의 생성자로만 이루어지는데, 생성자의 이름변경을 못하니 클래스메서드로 생성함수의 이름으로 명확하게 표현한걸로 보이네요,
이런 구현은 좋아보입니다.
| import java.util.List; | ||
|
|
||
| public class LottoWinningTicket { | ||
| private final LottoTicket winningTicket; |
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.
LottoTicket과 winningTicket은 같은 역할을 하는 객체일까?
LottoTicket의 공통적으로 필요한 부분만 추출해 하나의 클래스로 추출하고,
각각 필요한 기능은 각각의 클래스가 가지는 포함관계로 풀어보는것도 좋을거같아
| } | ||
|
|
||
| private Map<WinningSheet, Integer> makeStatistics(List<WinningSheet> winningSheets) { | ||
| Map<WinningSheet, Integer> statistics = new EnumMap<>(WinningSheet.class); |
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.
collect의 groupingBy를 쓰는게 더 깔끔할거같아
피드백 반영하고 최종 요구사항까지 구현하였습니다.
피드백 반영하면서 NumberGenerator 인터페이스의 이름을 고민하다가 실패하였습니다.