Skip to content
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

[서브웨이] 로또 2차미션 코드리뷰 요청입니다. #183

Merged
merged 44 commits into from
Mar 3, 2020

Conversation

joseph415
Copy link

No description provided.

전체 로또 티켓 갯수에서 수동으로 발급 받을때 갯수가 줄지 않는 버그 수정
0개를 수동으로 입력 받을때에도 발급되는 버그 수정
타입을 잘못 설정해 수익률 계산시 overflow되는 버그 발견하여 long타입으로 수정함
Copy link

@dave915 dave915 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서브웨이 구현하느라 고생하셨어요 👍
코멘트 남겼으니 확인 후 반영해보세요!

public static List<LottoBall> InputWinningTicket() {
try {
OutputView.printAnswerWinningBalls();
String winningTicket = scanner.nextLine();
LottoTicket winningTicketFactory = new LottoTicket(winningTicket);
LottoTicket winningTicketFactory = generateLottoTicket();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LottoTicket winningTicketFactory = generateLottoTicket(); 이부분은 우승 로또 Number 생성이라는 Domain로직으로 보는게 맞지 않을까요? View에서는 사용자에 대한 입력 및 출력 역활만 하면 좋을 것 같아요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

알겠습니다! 고치도록 하겠습니다.

manualTicketingCount = InputView.inputManualTicketingCount(ticketingTotalCount);

for (int i = 0; i < manualTicketingCount.getTicketingCount(); i++) {
LottoTickets.insertLottoTicket(new LottoTicket(InputView.InputManualLottoTicket()));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LottoTicket들을 LottoTickets가 Static 변수로 관리하고 있네요.
이렇게 되면 추후에 LottoGame이 다중의 사용자가 이용 할 수 있게 요청사항이 왔을때 어떤 문제가 있을까요?

@@ -28,15 +28,15 @@ public LottoTicket(List<LottoBall> lottoTicket) {
public LottoTicket(String inputValue){
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inputValue라는 파라미터 명보단 String LottoNumbers같은 내부에서 어떻게 쓰일지 알기쉽도록 변수명을 짓는게 좋을 것 같아요.

}

private static LottoTicket generateLottoTicket() {
String winningTicket = scanner.nextLine();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InputWinningTicket메소드 뿐만아니라 InputManualLottoTicket에서도 사용하고 있어서 winningTicket변수명은 수정해야 할 것 같아요!

}
}


private WinningTicket generateWinningBalls() {
try {
List<LottoBall> winningBallsInput = InputView.InputWinningTicket();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WinningTicket 내부에 코멘트를 남길 수 없어서 여기에 남겨요.
List<LottoBall> winningTicket에 일급 컬렉션을 적용해보면 어떨까요?
또, 적용해 보면서 LottoTicket과 합쳐서 여섯개의 중복되지 않은 로또넘버를 가지는 객체로 합칠 수 있는지 고민해볼까요?

ps. 현재 객체 생성에 관한 validation이 흩어져있는데 객체 생성에 관한 로직이나 validation은 각 객체 내부에서 담당하도록 수정해보면 어떨까요?

1000원 미안 입력시 예외처리
정수 이외의 다른 값 입력할 경우 재입력
음수인 경우 예외처리 구현
총 몇장을 구매할수 있는지 로또 총 티켓의 개수 구하는 기능구현
천원 단위가 아닌 나머지 금액은 반환하는 기능구현
도메인과 의존성이 생길수 있는 validate가 생겨서 제거하고 객체 안에서 구현하였습니다.
@joseph415
Copy link
Author

-리뷰-
LottoTicket들을 LottoTickets가 Static 변수로 관리하고 있네요.
이렇게 되면 추후에 LottoGame이 다중의 사용자가 이용 할 수 있게 요청사항이 왔을때 어떤 문제가 있을까요?

-질문-
이 말이 헷갈렸는데 다중사용자가 사용할경우 LottoTickets를 공유해서 문제가 생길수 있겟네요 ,,
static의 남발이 문제를 가져온다는게 이런것인지 드디어 알았네요!

  1. 구글링해서 어떤 정보를 보았는데 domain에서의 static을 최대한 지양해야 한다는데 이게 맞는 정보인지 궁금합니다!
  2. 그렇다면 싱글톤 패턴 사용도 지양되나요? 아님 그냥 유연하게 경우에 따라 다 다른것인지 궁금합니다!

@dave915
Copy link

dave915 commented Mar 2, 2020

  1. 구글링해서 어떤 정보를 보았는데 domain에서의 static을 최대한 지양해야 한다는데 이게 맞는 정보인지 궁금합니다!
    Domian 객체의 상태를 나타내는 필드에는 static을 사용하면 여러 인스턴스가 서로의 상태에 영향을 미치기 때문에 static 으로 선언 하면 안됩니다. 하지만 객체의 정적인 정보를 나타낼때는 사용해도 무관 하다고 생각해요 :)
    아래 링크도 읽어보세요!

https://unabated.tistory.com/entry/%EC%99%9C-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-static%EC%9D%98-%EC%82%AC%EC%9A%A9%EC%9D%84-%EC%A7%80%EC%96%91%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94%EA%B0%80

  1. 그렇다면 싱글톤 패턴 사용도 지양되나요? 아님 그냥 유연하게 경우에 따라 다 다른것인지 궁금합니다!
    싱글톤 패턴은 동일한 인스턴스를 재사용한다는 리소스적인 측면에서 이점이 있습니다. 하지만 싱글톤을 여러곳에서 호출하는 환경 (예를 들면 멀티쓰레드 환경) 등에서 사용할때 싱글톤이 상태를 지니게 되면 위 에서 이야기한 static 필드처럼 상태에 대해 무결성이 깨지기 때문에 주의해서 사용해야합니다.

Copy link

@dave915 dave915 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음 부터 다시 구현 하느라 고생 많으셨어요 👍
코멘트 몇개 남겼어요 확인 후 반영해주세요!
궁금한 점 있으시면 언제든 DM주세요 :)

return LOTTO_BALLS.stream()
.filter(x -> x.getLottoNumber() == lottoBallNumber)
.filter(Ball -> Ball.getLottoBall() == findLottoBall)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!!!! 🧐

ball -> ball.getLottoBall() == findLottoBall

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!!!😳

@@ -32,13 +34,16 @@ public static void shuffle() {
for (int i = 0; i < LOTTO_TICKET_SIZE; i++) {
lottoTicket.add(LOTTO_BALLS.get(i));
}

Collections.sort(lottoTicket);
return Collections.unmodifiableList(lottoTicket);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateLottoTicket요 메소드도 테스트 추가했으면 좋겠어요!

ValidateWinningTicketUtils.validateWinningBallsNumber(winningBalls);
ValidateWinningTicketUtils.validateWinningBallsLength(winningBalls);
ValidateWinningTicketUtils.validateDuplicatedWinningBalls(winningBalls);
//수동생성
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LottoTicket입장에선 수동 생성인지, 자동생성인지 관심이 없어서 주석은 지워도 될 것 같아요 :)

Comment on lines 56 to 60
public static void validateLottoUnit(String input) {
if (Integer.parseInt(input) < LOTTO_UNIT) {
throw new UnderLottoUnitMoney(String.format(UNDER_LOTTO_UNIT_RETURN_CHANGE, input));
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 클래스에서 error 메시지 변수명에 Lotto들어가는 Validation은 각 객체 안에서 해주면 좋을 것 같아요 :)

Comment on lines +46 to +50
lottoTickets.getLottoTickets()
.forEach(lottoTicket -> System.out.println(lottoTicket.getLottoTicket()
.stream()
.map(LottoBall::getLottoBall)
.collect(Collectors.toList())));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 메소드 분리 해주는게 좋을 것 같네요 :)

System.out.println(lottoTicket.getLottoTicket()
                        .stream()
                        .map(LottoBall::getLottoBall)
                        .collect(Collectors.toList()))

Copy link
Author

@joseph415 joseph415 Mar 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 분리하는 이유를 알수 있을까요?? 저는 결과를 출력하는 메소드명을 printLottoTicketAndChangeMoney 라고 지어서 저 로직을 안에 넣었는데
가독성 측면에서 좋아지는 이점이 있어서 나누는 걸까요??
아니면 하나의 기능만 하게 나눠야해서 나누는것일까요?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼭 메소드 분리가 아니더라도 람다식 안에 람다식이 중첩으로 들어가거나 함수 호출 시 람다식을 넣으면 다른 개발자가 봤을때 가독성이 떨어지게 됩니다 😭
적절하게 메소드분리 또는 변수 분리 해주세요.

그리고 또 이경우엔 lottoTicket에게 getLottoBallValues() 뭐 이런식으로 메세지를 보내서 Lotto의 숫자들을 제공하는 책임을 주는게 좋지 않을까요?


public class LottoController {
public void play() {
Money money = generateMoney();
LottoTicketCount autoTicketLottoTicketCount = new LottoTicketCount(money.generateLottoTicketCount());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

autoTicketLottoTicketCount의 ticketCount가 생성 시점에 정해지는것이 아니라 generateAutoTicket메소드 호출 후에 정해지네요.
generateAutoTicket메소드 호출 전에 autoTicketLottoTicketCount을 사용하게 되면 원하는 의도와 다르게 동작 할 것 같네요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

autoTicketLottoTicketCount 를 allTicketLottoTicketCount 로 바꿔주어 의미를 좀 명확하게 나타냈습니다!

if (Double.isInfinite(calculateEarningRate(purchaseAmount))
|| Double.isNaN(calculateEarningRate(purchaseAmount))) {
throw new IllegalArgumentException(ILLEGAL_PURCHASE_AMOUNT);
for (Rank r : rank) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rank r 축약어는 지양해 주세요!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List<Rank> rank 를 ranks로 선언 하면 될 것 같아요 :)

Suggested change
for (Rank r : rank) {
for (Rank rank : ranks) {

Copy link

@dave915 dave915 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 서브웨이 :)
처음 PR주셨을때 보다 많이 깔끔해졌네요 💯
코멘트 몇개 남겼으니 확인 해 보세요!
수고하셨습니다. 머지할게요!

if (Double.isInfinite(calculateEarningRate(purchaseAmount))
|| Double.isNaN(calculateEarningRate(purchaseAmount))) {
throw new IllegalArgumentException(ILLEGAL_PURCHASE_AMOUNT);
for (Rank r : rank) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List<Rank> rank 를 ranks로 선언 하면 될 것 같아요 :)

Suggested change
for (Rank r : rank) {
for (Rank rank : ranks) {

Comment on lines +46 to +50
lottoTickets.getLottoTickets()
.forEach(lottoTicket -> System.out.println(lottoTicket.getLottoTicket()
.stream()
.map(LottoBall::getLottoBall)
.collect(Collectors.toList())));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼭 메소드 분리가 아니더라도 람다식 안에 람다식이 중첩으로 들어가거나 함수 호출 시 람다식을 넣으면 다른 개발자가 봤을때 가독성이 떨어지게 됩니다 😭
적절하게 메소드분리 또는 변수 분리 해주세요.

그리고 또 이경우엔 lottoTicket에게 getLottoBallValues() 뭐 이런식으로 메세지를 보내서 Lotto의 숫자들을 제공하는 책임을 주는게 좋지 않을까요?

WinningTicket winningTicket = new WinningTicket(winningBallValues, 7);
@DisplayName("몇개 맞추는지 test")
void hitLottoBallTest() {
LottoTicket lottoTicket = new LottoTicket("1,2,3,4,5,6");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적으로 new LottoTicket 대신 LottoTicket.of 로 해야 되는것 같은데요? :)

Suggested change
LottoTicket lottoTicket = new LottoTicket("1,2,3,4,5,6");
LottoTicket lottoTicket = LottoTicket.of("1,2,3,4,5,6");

private static final Scanner SCANNER = new Scanner(System.in);

public static String inputMoney(){
OutputView.printInputMoney();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이경우는 InputView도 View이기 때문에 OutputView를 호출 안하고 바로 System.out.println을 사용해도 될 것 같아요!

@dave915 dave915 merged commit e809e23 into woowacourse:joseph415 Mar 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants