Skip to content

[SCG] 권승원 로또 1-2단계 미션 제출합니다.#162

Open
zest-sw wants to merge 7 commits intonext-step:mainfrom
zest-sw:main
Open

[SCG] 권승원 로또 1-2단계 미션 제출합니다.#162
zest-sw wants to merge 7 commits intonext-step:mainfrom
zest-sw:main

Conversation

@zest-sw
Copy link
Copy Markdown

@zest-sw zest-sw commented Apr 2, 2026

인사

안녕하세요! 제용님. 이번 미션 완료하여 pr 리뷰 부탁드립니다.
저는 자바는 잘 안 써봐서 미숙하긴 하나 이번 기회를 통해서 많이 알아가는 것 같습니다.
이번에 페어 프로그래밍하면서 색다른 경험을 한 것 같네요!

고민했던 부분

  • 로또 티켓 객체가 특별한 메서드를 제공하지 않아서 그냥 컬렉션을 사용하는 것과 비슷한 것 같은 느낌이 들었습니다.
  • 코드에서 tickets를 그냥 리스트로 받아서 tickets.get(0).getTicketNumbers()와 같이 사용되어서 가독성이 좀 떨어진다고 느꼈습니다.
  • Statisitc 객체를 테스트 할 때, util/sequenceGenerator 를 사용했는데 티켓이 2장 이상이 되면 사용이 직관적이지 않다고 느꼈습니다.
  • 코드 중간중간에 List로 그냥 쓸 때가 있고, 이번 미션의 일급 컬렉션 조건을 충족을 위해 ticket은 일급 컬렉션으로 구성했는데, 모두 다 일급 컬렉션으로 만드는 것이 나을까요? 오히려 복잡성만 증가하는 걸까요?

잘 부탁드립니다!!

Copy link
Copy Markdown

@jeyongsong jeyongsong left a comment

Choose a reason for hiding this comment

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

안녕하세요 승원님! 송제용이라고 합니다! 잘 부탁드려요 ㅎㅎㅎ

이번 미션 구현하시느라 고생 많으셨습니다.
자바가 익숙하지 않다고 하셨는데도, 전체적으로 역할을 나누려는 흐름이 보여서 좋게 읽었습니다!
(사실 이 정도의 코드면 바로 Approve해도 문제 없다고 개인적으로 생각합니다 ㅋㅋㅋ)

특히 NumberGenerator 인터페이스를 두고 RandomNumberGenerator, SequenceGenerator를 분리한 점이 좋았어요.
덕분에 랜덤 생성 로직과 테스트용 생성 로직을 분리할 수 있어서, “제어할 수 없는 값”을 테스트 가능하게 바꾸려는 고민이 잘 드러났습니다.
페어 프로그래밍하면서 이런 구조를 같이 가져가신 것도 되게 좋은 경험이셨을 것 같아요. (힘들지는 않으셨나요? ㅋㅋㅋㅋ 저도 페어 프로그래밍할 때 많이 싸웠습니다 하하하)

말씀 주신 고민 포인트들도 다 좋은 고민이었습니다! 코멘트에서 다루었으니 확인해주시고 생각을 공유해주시면 감사하겠습니다!

전체적으로 방향은 좋아서, 조금만 더 다듬으면 더 읽기 편한 코드가 될 것 같아요! 화이팅!!

return tickets;
}

private LottoTicket generateTicket() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

로또 자동 구매 힌트에 Collections.shuffle() 활용 이야기가 적혀 있었는데, 사용하지 않으신 건 의도하신 걸까요???? 🙋 (저는 이런 일탈도 좋아해요! ㅋㅋㅋㅋ)

단순히 “안 썼다”가 궁금한 건 아니고, 현재 방식처럼 중복을 검사하면서 뽑는 방식으로 가져가신 의도가 궁금했습니당!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

실망하실지도 모르겠지만.... 작업을 하면서 리드미에 다 할 일을 옮겨두어서 리드미만 보고 작업해서 힌트를 못 본게 가장 큰 원인이었습니다... ㅋㅋㅋㅋㅋ 음.... 이제 생각해보니 바구니를 섞어서 뽑는다고 생각하면 shuffle이 이치에 맞는 것 같습니다 하하;;

Comment on lines +12 to +16
public class Controller {
InputView inputView = new InputView();
OutputView outputView = new OutputView();
LottoService lottoService = new LottoService(new RandomNumberGenerator());
Statistic statistic = new Statistic();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Controller 안에서 필요한 객체들을 직접 생성하고 있어서, 현재는 동작에는 문제가 없지만 테스트하거나 조합을 바꾸고 싶을 때 조금 덜 유연해질 수 있을 것 같아요!
혹시 해당 방식으로 구현하신 의도가 궁금합니다! 🙋 (수정이 필요하다는 뜻은 아니에용)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

컨트롤러가 어플리케이션의 흐름의 관리하는 가장 상위 객체라고 생각해서 만약에 이것들이 바뀌면 문제 자체가 바뀐다고 생각해서 수정을 한다면 컨트롤러를 수정하는 걸 생각했습니다. main에서 컨트롤러가 객체를 받으면 조금 더 유연해질 수도 있겠군요! 만약 컨트롤러에서 사용하는 객체들을 유연하게 바꿀 필요가 있다면 그렇게 설계하는 것도 좋을 것 같네요!! 감사합니다.

Comment on lines +9 to +12
public LottoTicket (List<Integer> lottoNumbers) {
this.lottoNumbers = lottoNumbers;
Collections.sort(this.lottoNumbers);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LottoTicket 생성자에서 받은 리스트를 그대로 들고 있고, 정렬도 원본 리스트에 직접 적용하고 있어서
외부에서 넘긴 리스트와 객체 내부 상태가 같이 바뀔 여지가 있어 보여요!

지금 단계에서는 크게 문제 없을 수 있지만,
도메인 객체가 자기 상태를 더 안전하게 관리하려면 내부에서 복사해서 보관하는 것도 고려해볼 수 있을 것 같습니다! (저희는 협업이 기본인데 혹쉬 모르잖아요? ㅋㅋㅋㅋ)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

엇 this.lottoNumbers에 해서 객체 내부의 상태를 바꾼다고 생각했는데 아닌가요?!!?!

Comment on lines +13 to +14
public static final int MATCHED_TRHEE_COUNT = 3;
public static final int MATHCED_FOUR_COUNT = 4;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

사소하지만 상수명에 오타가 조금 보여서 (MATCHED_TRHEE_COUNT, MATHCED_FOUR_COUNT)
나중에 읽는 사람 입장에서는 살짝 헷갈릴 수 있을 것 같아요!
(페어프로그래밍 정신 없죠? ㅋㅋㅋㅋㅋㅋㅋ)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

앗 ㅋㅋㅋㅋ 둘 다 못 잡았네요

Comment on lines +16 to +20
public void testWinningResult() {
//given
List<Integer> sequence = List.of(1, 5, 3, 2, 6, 7, 11, 12, 13, 14, 15, 16);

NumberGenerator numberGenerator = new SequenceGenerator(sequence);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

승원님이 적어주신 고민에 저도 공감했어요! ㅋㅋㅋㅋ
지금처럼 SequenceGenerator로 고정값을 흘려보내는 방식은 테스트 가능성을 만든 점은 좋지만,
티켓이 여러 장이 되는 순간 “이 수열이 어떤 티켓들을 만들기 위한 값인지”가 한 번에 잘 안 들어올 수 있겠더라고요. (가끔 술 한잔하고 코딩할 떄도 많으니까요?)

그래서 개인적으로는 이럴 때 두 방향을 많이 고민합니다~

  • 생성 로직을 조금 더 쪼개서 “티켓 1장 생성”을 더 직접 테스트하기
  • 테스트 전용 빌더/팩토리 느낌으로 의도를 더 잘 드러내기

즉, 지금 방식이 틀렸다기보다,
테스트가 제어 가능해진 건 좋은데 의도가 잘 읽히는지를 다음 단계에서 한 번 더 개선해보면 좋을 것 같아용~!
승원님이 가장 어려웠다고 적어주신 포인트가 정확히 좋은 고민 지점이었습니다!! 고수네요!


import java.util.List;

public class SequenceGenerator implements NumberGenerator{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SequenceGenerator가 지금 프로덕션 코드(src/main)에 위치해 있는데, 이게 여기 있는 게 맞을까? 하는 생각이 들었어요 🙋

현재 역할을 보면 테스트에서 고정된 값을 만들기 위한 구현체에 가까워 보이는데,
혹시 나중에 실제 코드에서 잘못 사용될 가능성은 없을까요? (예를 들어 술 마신 상태에서(?) 잘못 끼워넣는다든지요 ㅋㅋ)

이 부분은 어떻게 생각하셨는지 궁금합니다!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

테스트 코드에 필요한 코드는 테스트에 넣어도 된다는 생각을 못했네요! 그게 더 이 코드를 위한 위치인 건 합리적인 것 같습니다! (음주 코딩은 지양해야겠지만요....ㅋㅋㅋ)

Comment on lines +18 to +19
public List<Integer> getWinningResult(List<LottoTicket> lottoTickets, List<Integer> winningNumbers) {
List<Integer> winningResult = new ArrayList<>(List.of(0, 0, 0, 0, 0, 0, 0));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

winningResult를 List로 두고,
일치 개수를 그대로 인덱스로 사용하는 방식은 구현은 간단한데 읽을 때는 조금 해석이 필요하더라고요!

예를 들어

  • winningResult.get(3)
  • winningResult.get(4)

이런 코드는 “왜 3이지?”, “왜 4지?”를 한 번 더 생각하게 만드는 느낌이 있었습니다.

그래서 추후에는

  • 당첨 결과를 표현하는 별도 객체를 두거나
  • 최소한 의미 있는 메서드로 감싸거나
  • enum / map 구조를 고민해보는 것

도 좋을 것 같습니다!!

지금도 동작은 되지만, 통계 관련 코드는 의미가 잘 드러나는 표현이 특히 중요해서 한 번 말씀드려봤어요 ㅎㅎㅎ

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

아하! 그럴 수 있겠네요! get만 있으니 해석이 좀 필요하게 되네요. 조언 감사합니다!

Comment on lines +17 to +25
public List<LottoTicket> buyTickets(int money) {
validateMoney(money);
int ticketCount = money/ TICKET_PRICE;

List<LottoTicket> tickets = new ArrayList<>();

for(int i=0;i<ticketCount;i++){
tickets.add(generateTicket());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

말씀 주신 tickets.get(0).getTicketNumbers() 같은 사용 방식은, tickets가 단순 List로 노출되어 있어서 생기는 문제처럼 느껴졌습니다!

그래서 이 부분은 LottoTickets처럼 한 번 감싸는 방향도 떠올랐는데, 저도 바로 “그럼 모든 컬렉션을 다 일급 컬렉션으로 만들어야 하나?”라는 고민이 이어지더라고요 ㅋㅋ 어떻게 하면 좋을까요??

(저는 이 죽음의 이지선다에 살아남을 수 있는 방법을 만들어두어서 너무 편하더라고요! 이 기회에 승원님도 하나 만들어보시죠!)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

아아 그쵸!! 저만의 기준을 세워야겠네요... 지금 생각나는 기준은.. 지금 처럼 코드가독성이 별로인 부분은 사용하는 게 좋을 것 같아요!! 요즘 assertj에서 "코드를 이런 식으로 영어원문 처럼 짤 수도 있구나"라고 감탄해서 그렇게 표현 방식을 다르게 해서 얻는 이득이 지금처럼 크다면 바꾸는게 좋은 것 같습니다. 생각할 기회를 주셔서 감사합니다

@jeyongsong
Copy link
Copy Markdown

아! 다음 step2 는 step2 브랜치에서 작업해주세용! (깃허브 연습도 할겸!)

image

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