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

[로또] 송지은 미션 제출합니다. #70

Open
wants to merge 9 commits into
base: hafnium1923
Choose a base branch
from

Conversation

hafnium1923
Copy link

안녕하세요 리뷰어님!! 오랜만에 미션을 제출하네요..
개인적인 사정 이해해주시고 기한 늦춰주셔서 정말 감사합니다🙏
덕분에 열심히 시험보고 있어요ㅎㅎ

미션 설명 & 구조 설명

이번 미션에서는 사용자가 입력한 금액에 따라 로또 티켓을 발급하고, 당첨 번호와 비교하여 당첨 결과를 출력하는 로또 애플리케이션을 구현하였습니다. 애플리케이션은 다음과 같은 주요 컴포넌트로 구성되어 있습니다:

  • Controller: LottoController는 애플리케이션의 전체 흐름을 관리하며, 사용자 입력과 출력을 조율합니다.
  • Domain:
    • Lotto: 로또 티켓 생성 및 관련 비즈니스 로직을 담당합니다.
    • LottoNumber: 로또 번호를 표현하는 값 객체입니다.
    • LottoTicket: 하나의 로또 티켓을 나타내며, 로또 번호 리스트를 포함합니다.
    • LottoResult: 당첨 결과를 계산하고 저장하는 역할을 합니다.
    • Prize: 당첨 등수를 나타내는 Enum으로, 각 등수별 매칭 조건과 상금을 정의합니다.
  • View:
    • InputView: 사용자로부터 입력을 받는 역할을 합니다.
    • OutputView: 결과를 사용자에게 출력하는 역할을 합니다.
  • Main: 애플리케이션 실행의 진입점입니다.
  • 테스트: JUnit을 활용하여 각 도메인 객체의 동작을 검증하는 테스트 케이스를 작성하였습니다.

개인적으로 어려웠던 부분 🛠️

컬렉션 사용하기:
컬렉션이 뭘까부터 고민했던 것 같습니다. 특히, 모든 원시 값과 문자열을 포장하면서 컬렉션을 사용하는 부분에서 좀 헷갈렸던 것 같아요. �컬렉션 사용하면서 에러뜨는거 해결하려고 이상한 인터페이스도 확장하고 숫자 하나조차도 클래스로 포장하면서 이게 맞나..? 라는 생각이 많이 들었습니다. 너무 구조가 복잡해진?듯?

일급 컬렉션 사용하기:
LottoTicket을 일급 컬렉션으로 구현했습니다. 하.. 이것 때문에 로또 번호도 클래스로 분리한건데 너무 어려워요.

Java Enum 적용:
Prize Enum을 설계하면서 각 등수별 매칭 조건과 상금 금액을 효율적으로 관리하는 방법을 고민했습니다. 개념은 알고 있어서 그렇게 어렵진 않았는데 좋은 구조를 생각하느라 오래걸렸던 것 같네요

결론

컬렉션을 사용하기 위해서는 정말 하나하나 다 클래스로 래핑해야하나요? 혹시라도 더 좋은 방법이 있다면 공유해주세요. 이번 미션 너무너무 어려웠는데 리뷰어님은 어떠셨나요?ㅠ

이번 리뷰도 잘 부탁드립니다.!

Copy link

@wzrabbit wzrabbit left a comment

Choose a reason for hiding this comment

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

@hafnium1923 👋🏻

안녕하세요 루루~ 설날이라 쉬고 있는 와중에도 미션 구현이라니 눈물겹습니다 😓 벌써 연휴의 중반부인데 잘 쉬고 계실지 궁금하네요.

리뷰, 그리고 미션에 대해서 이야기를 하자면 도메인이 2주차와 비교했을 때 더 복잡하게 얽히고, 비슷한 성격을 지니는 도메인(당첨 로또, 수동 로또)들이 생기면서 일급 컬렉션 도메인 도입에 대한 고민을 많이 했던 것 같아요. 그래서 리뷰는 일급 컬렉션, 그리고 우리가 항상 고민하고 또 고민하던 검증 로직을 중심으로 진행했답니다.

남은 연휴도 잘 보내요~

Comment on lines +18 to +20
int amount = Integer.parseInt(input);
if (amount > 0 && amount % Lotto.LOTTO_PRICE == 0) {
return amount;

Choose a reason for hiding this comment

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

$3\,500$ 같은, 정수 포맷은 준수하지만 도메인 특성상 올바르지 않은 값이 입력되었을 때는 NumberFormatException를 catch하는 분기로 넘어가지 않을 것 같아보이고, 그 결과 아무 에러 메시지 없이 값을 다시 입력받도록 작동할 것 같아보여요.

NumberFormatExceptionIllegalArgumentException 모두를 catch하되 구분해서 처리할 수 있는 방법은 없을까요?

Comment on lines +22 to +24
} catch (NumberFormatException e) {
System.out.println("1000원 단위 유효한 숫자를 입력해주세요. 다시 시도해주세요.");
}

Choose a reason for hiding this comment

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

오 이럴 때 NumberFormaxException 을 쓰는거군요 지금까지 아예 잘못된 포맷(정수 입력하라는데 문자열!?)을 입력하는 것에 대한 예외는 생각해보지 않았는데 배워갑니다 😋

winningNumbers.add(new LottoNumber(num));
}

long distinctCount = winningNumbers.stream().distinct().count();

Choose a reason for hiding this comment

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

오... HashSet 같은 걸 선언하지 않고 바로 streamdistinct 를 사용해서 중복값이 아닌 값의 개수를 세는 것도 가능하군요. 저는 filter를 사용했던 것 같은데 왜인지 모르게 너무 복잡하게 구현한듯한 느낌이 들었어요. stream 을 사용한 코드는 루루 코드를 좀 참고해야겠어요 😈

Comment on lines +83 to +103
try {
String[] tokens = input.split(",");
if (tokens.length != 6) {
throw new IllegalArgumentException("당첨 번호는 6개여야 합니다.");
}

List<LottoNumber> winningNumbers = new ArrayList<>();
for (String token : tokens) {
int num = Integer.parseInt(token.trim());
winningNumbers.add(new LottoNumber(num));
}

long distinctCount = winningNumbers.stream().distinct().count();
if (distinctCount != 6) {
throw new IllegalArgumentException("당첨 번호는 중복될 수 없습니다.");
}

return winningNumbers;
} catch (IllegalArgumentException e) {
System.out.println("유효한 당첨 번호를 입력해주세요. 예: 1,2,3,4,5,6");
}

Choose a reason for hiding this comment

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

철저하게 예외 처리를 분기해 주신 것은 정말 좋지만! 아쉽게도 IllegalArgumentException 을 catch하는 catch문 내부에서는 발생 이유와 별개로 항상 "유효한 당첨 번호를 입력해주세요. 예: 1,2,3,4,5,6" 에러 메시지만 출력될 것이 예상되는 상황입니다. catch문 내부에서 그 메시지의 내용을 받아와서 출력하는 것은 어떨까요?

다른 예외 처리문에서도 비슷한 형태의 코드로 짜여있어서, 이 문제를 공유할 것 같다는 느낌도 듭니다


public class OutputView {
public void printPurchaseLotto(int manualCount, int autoCount, List<LottoTicket> lottoTickets) {
System.out.printf("수동으로 %d장, 자동으로 %d개를 구매했습니다.\n", manualCount, autoCount);

Choose a reason for hiding this comment

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

오... printf 를 이용해 이렇게 깔끔하게 처리하는 방법도 있군요

import java.util.Collections;
import java.util.List;

public class Lotto {

Choose a reason for hiding this comment

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

개인적으로 LottoLottoTicket 클래스의 이름이 다소 헷갈리게 느껴졌던 것 같아요, 저는 Lotto 를 로또 하나(6개의 정수를 담고 있는 리스트 형태의 컬렉션) 이라고 생각했는데, 내부를 보니 Lotto 는 로또 생성을 위한 전반적인 도메인들을 다루고 있는 것으로 보였어요. LottoTicket 이 오히려 제가 생각했던 로또의 기능을 담당하더라고요.

  • Lotto 의 이름을 구체적으로 바꿔볼 수 있을까요?

Choose a reason for hiding this comment

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

enum 사용 경험이 있으시다고 해서, enum 사용 여부에 대해 여쭤보고 싶은 점이 있습니다

  • 어떤 곳에서는 enum 을 사용하지 않으셨고, 어떤 곳에서는 enum 을 사용하셨는데, 그 기준을 어떻게 두셨나요?
  • 일반 클래스 내부에 상수들을 선언하고 getter 로 리턴할 수 있도록 관리하는 방법과 enum 을 사용하여 관리하는 방법은 어떤 차이가 있을까요?


import java.util.Collections;
import java.util.List;
import java.util.Objects;

Choose a reason for hiding this comment

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

Suggested change
import java.util.Objects;

안 쓰이는 import문으로 보이는 것 같아요 ✏️

Comment on lines +24 to +26
public boolean isHasBonus() {
return hasBonus;
}

Choose a reason for hiding this comment

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

Suggested change
public boolean isHasBonus() {
return hasBonus;
}

안 쓰이는 메서드로 보이는 것 같아요 ✏️

Comment on lines +10 to +11
private static final int MIN_LOTTO_NUMBER = 1;
private static final int MAX_LOTTO_NUMBER = 45;

Choose a reason for hiding this comment

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

이 두 값들을 InputView 에서도 사용해 보는 것은 어떨까요?

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.

2 participants