[SCG] 손희창 로또 1-2단계 미션 제출합니다.#161
Conversation
객체 스스로 비교연산을 진행할 수 있도록 로직을 추가함.
…서 한번에 세개의 정보(matchNumbers,prizeMoney,등수별 당첨횟수)를 저장하여 계산함.
m-a-king
left a comment
There was a problem hiding this comment.
페어프로그래밍을 이번에 처음하다보니 많은 시간이 소요되고 그 시간들이 정말 소중한 시간이였던 것 같습니다. 미션 해결을 하며 파트너에게 감탄하고 협업 능력을 기르고 이 미션에 대한 프로그래밍 기여도를 위해 승부욕이 좀 불타오르는 미션이였던 것 같습니다. 어떤 사람에게 코드에 대한 제 생각을 공유하는 것도 연습할 수 있었고 파트너가 제안한 코드 로직과 형식을 이해하는 시간도 너무 좋았습니다. 힘든 만큼 얻어간건 확실히 많았던 것 같습니다.
너무 부럽습니다. 저도 페어프로그래밍 참 좋아해요~ 제 리뷰도 페어와 함께 공유하고, 혼자 해결하기에 어려운 문제가 있다면 함께 해결하셔도 좋습니다!
또한 원시값을 포장하는 요구사항과 일급컬렉션을 사용하라는 요구사항이 발목을 많이 잡았습니다.
하지만 파트너와 최선을 다해 요구사항을 충족시키며 코드를 만들고자 하였습니다.
저도 요구사항에 자주 반항했던 기억이 나네요 ㅎㅎ
이해할 수 없는 요구사항이 주어진다면 그 이유를 적어주시고, 지키지 않으셔도 좋습니다~
그럼 제가 지키게 해드릴게요! 😄
완성하지 못한 부분
메서드 분리가 필요한 메서드가 많은 것 같습니다.
어떤 부분인가요?
저희가 짠 코드가 모든 원시값을 포장했다고 볼 수 있는지 궁금합니다.
네! 잘 지켜주셨습니다. 그치만 원시값 포장이라는 목표에 진짜 의미가 무엇인지 돌아보면 개선할 수 있는 부분이 많은 것 같아요~
일급 컬렉션을 잘 만들고 활용했는지 궁금합니다.
아니요... 이 부분은 상당히 아쉬웠습니다. 어떻게 일급 컬렉션을 잘 활용할 수 있을지 조금 더 학습이 필요하다고 생각합니다. 제가 진짜 잘 알려드릴게요!
하나의 메서드는 하나의 기능을 가져야하는데 책임을 너무 과하게 많이 가진 메서드가 보이시는 지 궁금합니다.
전체적으로 메서드는 잘게 나눠주신 것 같습니다. 그 과정에서 각 메서드들의 위치가 올바른지에 대해서 심도있는 토론을 해보고 싶어요~
이번에는 파트너와 함께 작성했지만 자바에 아직 미숙한 점이 많고 배우는 과정이다보니 부족한 점이 많을 수 있습니다. 잘못된 점이 있다면 말씀주시고 궁금한 부분에 대한 멋진 답변 부탁드립니다! 리뷰어님!
멋집니다 희창님 화이팅!!
src/main/java/domain/Lotto.java
Outdated
| import java.util.List; | ||
|
|
||
| public class Lotto { | ||
| public static final int LOTTO_SIZE = 6; |
There was a problem hiding this comment.
lotto size 라는 상수 명을 어떻게 하면 더 직관적으로 개선할 수 있을까요?
There was a problem hiding this comment.
네 좋습니다!
저라면 클래스 이름이 문맥을 담고 있으니 NUMBER_COUNT(Lotto.NUMBER_COUNT)로 사용할 수 있지 않을까? 생각합니다~
src/main/java/domain/Lotto.java
Outdated
| private final List<LottoNumber> numbers; | ||
|
|
||
| public Lotto(List<LottoNumber> numbers) { | ||
| validatorLotto(numbers); |
There was a problem hiding this comment.
validator은 자바 메서드 네이밍 컨벤션에 맞지 않는 것 같아요~
src/main/java/domain/Lotto.java
Outdated
|
|
||
| public class Lotto { | ||
| public static final int LOTTO_SIZE = 6; | ||
| private final List<LottoNumber> numbers; |
There was a problem hiding this comment.
List<LottoNumber>은 LottoNumbers로 묶지 않은 이유가 있나요?
There was a problem hiding this comment.
Set는 순서가 없는 컬렉션이라 저에게 익숙치 않아서 List를 택했습니다.
또한
// RandomLottoGenerator.java
public RandomLottoGenerator(){
this.seedNumbers = initializeNumbers();
}
private List<Integer> initializeNumbers(){
List<Integer> numbers = new ArrayList<>();
for(int i = MIN_NUMBER;i<=MAX_NUMBER;i++){
numbers.add(i);
}
return numbers;
}
public Lotto generate(){
Collections.shuffle(seedNumbers);
List<Integer> LottoNumbers = new ArrayList<>(seedNumbers.subList(0,LOTTO_SIZE));
Collections.sort(LottoNumbers);
return parseLN(LottoNumbers);
}
이 로직을 구현할때 참고한 문서가 리스트를 활용했기 때문이기도 합니다.
Set로 표현했다면 subList대신 subSet를 활용하게 되나요?
shuffle을 못쓰게 되면 어떻게 랜덤한 숫자를 뽑을 수 있을 지가 떠오르지 않네요...
There was a problem hiding this comment.
어떤 방법이 있을까요~
간단하게는 Set의 크기가 Lotto.NUMBER_COUNT가 될 때까지 숫자를 반복해서 뽑는 방법도 있을 것 같아요.
다만 이 방식은 중복이 계속 나오면 반복 횟수가 늘어날 수 있어서, 완료 시간의 상한 문제가 있네요...
Lotto를 생성하는 쪽에서 Collection을 받아 Lotto 내부적으로 생성 검증 이후에 Set으로 변환하면, 호출부는 단순하게 유지하면서도 Lotto가 중복 없는 번호 집합이라는 점을 스스로 보장할 수 있을 것 같습니다! 이 내용은 깊이가 좀 있네요. 이해가 안되시면 꼭 다시 물어봐주세요~
| public List<LottoNumber> getLotto() { | ||
| return numbers; | ||
| } |
There was a problem hiding this comment.
여기서 Lotto는 클래스 명을 따르며 6개 숫자를 묶은 로또 한개를 의미했고 변수설정을 위에서 numbers로 했는데 이것도 6개 숫자를 묶은 로또 한개를 의미했습니다. 다른 사람이 보기에 너무 헷갈릴 것 같아
private final List<LottoNumber> numbers;
를 말씀 주신 대로
private final List<LottoNumber> lottoNumbers;로 변수명을 설정해보는 것이 좋아보입니다.
혹시나 클래스명도 LottoNumbers로 바꿀 필요가 있을까요..?
저는 Lotto로도 충분해보이긴 합니다.
There was a problem hiding this comment.
아하 제 질문 의도는 getNumbers 혹은 getLottoNumbers가 맞지 않을까? 입니다 ㅎㅎ
취향 차이이긴 한데, 저는 클래스 이름이 이미 문맥을 설명하고 있다면 필드명이나 메서드명에서 그 이름을 반복하지 않는 편이 더 좋더라고요~ 그래서 getNumbers가 가장 좋다고 생각해요!
| public List<LottoNumber> getLotto() { | ||
| return numbers; | ||
| } |
There was a problem hiding this comment.
외부에서 lotto.getLotto()를 호출하고, 로또 넘버를 바꿀 수 있는 상황에 대해서 어떻게 생각하시나요?
There was a problem hiding this comment.
(현재 numbers를 lottoNumbers로 변수명 바꿈)
Lotto.java에서는 private final List lottoNumbers;
LottoNumber.java에서는 private final int number;로 private를 붙여도 로또 넘버를 바꿀 수 있는 상황이 생기는 건가요??
There was a problem hiding this comment.
final은 이 변수가 가리키는 주소를 바꿀 수 없다는 뜻입니다! 그래서 리스트를 바라보는 참조를 변경할 수는 없어요.
그치만 리스트 안의 요소를 변경할 수 있습니다. add, remove, clear 같은 조작이 가능해요~
여기서 헷갈릴 수 있는 부분이 있는데, 리스트 안의 LottoNumber도 final입니다. 그래서 내부적인 int 값은 못 바꿔요. 하지만 이건 그 객체의 값 변경을 막는 거고, 리스트에서 그 객체를 빼거나 넣는 건 리스트의 동작이라 별개입니다. 즉, 요소 자체를 삭제하거나 추가하는 것은 막을 수 없어요.
이런 동작을 막기 위해서는 어떻게 해야할까요? 학습해보시면 좋을 것 같습니다!
README.md
Outdated
|
|
||
| ## 새로운 프로그래밍 요구사항 | ||
|
|
||
| - [ ] 모든 원시 값과 문자열을 포장한다. |
There was a problem hiding this comment.
리뷰어님이 이부분은 칭찬해주셨으니 과감하게 [x]표시를 해보도록 하겠습니다..ㅎㅎ
| } | ||
|
|
||
| public void valueAdd(Rank rank) { | ||
| result.put(rank, result.get(rank) + 1); |
There was a problem hiding this comment.
앗 제가 Enum부분을 처음 다뤄봐 마땅한 해결책은 모르겠네요..
There was a problem hiding this comment.
이후 ENUM 관련 학습을 진행하면서 수정해봐도 좋을 것 같아요~
미리 학습해보셔도 좋습니다.
| import java.util.LinkedHashMap; | ||
| import java.util.Map; | ||
|
|
||
| public class LottoCalculator { |
There was a problem hiding this comment.
겹침 횟수에 따라 상금을 누적하는 역할을 합니다. 이부분도 저에게 생소한 Enum관련된 로직이 있어 설명이 안되네요...
| } | ||
|
|
||
| @Override | ||
|
|
|
|
||
| import java.util.List; | ||
|
|
||
| public class Lottos { |
There was a problem hiding this comment.
Lottos 클래스가 더 많은 일을 할 수 있을 것 같아요! 30줄 이상으로 만들어보는 미션을 드리고 싶어요~
There was a problem hiding this comment.
아앗.. lottos 클래스가 검증하기도 애매하고 무슨 일을 해야할지 잘 모르겠어요..
There was a problem hiding this comment.
음... 사용자가 돈을 내면 로또가 하나 이상 생성되잖아요? 그 생성부터 결과 확인까지, 여러 장의 로또를 가지고 해야 하는 일들을 생각해보세요. 기존 클래스를 삭제해도 좋습니다!
m-a-king
left a comment
There was a problem hiding this comment.
수고하셨습니다! 희창님과 많은 코멘트를 주고 받고 싶었는데 시간이 아쉽네요 ㅠㅠ
끝맺지 못한 질문은 다음 3-4단계 미션에서 주고 받아요~
| public List<LottoNumber> getLotto() { | ||
| return numbers; | ||
| } |
There was a problem hiding this comment.
아하 제 질문 의도는 getNumbers 혹은 getLottoNumbers가 맞지 않을까? 입니다 ㅎㅎ
취향 차이이긴 한데, 저는 클래스 이름이 이미 문맥을 설명하고 있다면 필드명이나 메서드명에서 그 이름을 반복하지 않는 편이 더 좋더라고요~ 그래서 getNumbers가 가장 좋다고 생각해요!
src/main/java/domain/Lotto.java
Outdated
| import java.util.List; | ||
|
|
||
| public class Lotto { | ||
| public static final int LOTTO_SIZE = 6; |
There was a problem hiding this comment.
네 좋습니다!
저라면 클래스 이름이 문맥을 담고 있으니 NUMBER_COUNT(Lotto.NUMBER_COUNT)로 사용할 수 있지 않을까? 생각합니다~
src/main/java/domain/Lotto.java
Outdated
| private final List<LottoNumber> numbers; | ||
|
|
||
| public Lotto(List<LottoNumber> numbers) { | ||
| validatorLotto(numbers); |
src/main/java/domain/Lotto.java
Outdated
|
|
||
| public class Lotto { | ||
| public static final int LOTTO_SIZE = 6; | ||
| private final List<LottoNumber> numbers; |
There was a problem hiding this comment.
어떤 방법이 있을까요~
간단하게는 Set의 크기가 Lotto.NUMBER_COUNT가 될 때까지 숫자를 반복해서 뽑는 방법도 있을 것 같아요.
다만 이 방식은 중복이 계속 나오면 반복 횟수가 늘어날 수 있어서, 완료 시간의 상한 문제가 있네요...
Lotto를 생성하는 쪽에서 Collection을 받아 Lotto 내부적으로 생성 검증 이후에 Set으로 변환하면, 호출부는 단순하게 유지하면서도 Lotto가 중복 없는 번호 집합이라는 점을 스스로 보장할 수 있을 것 같습니다! 이 내용은 깊이가 좀 있네요. 이해가 안되시면 꼭 다시 물어봐주세요~
| public List<LottoNumber> getLotto() { | ||
| return numbers; | ||
| } |
There was a problem hiding this comment.
final은 이 변수가 가리키는 주소를 바꿀 수 없다는 뜻입니다! 그래서 리스트를 바라보는 참조를 변경할 수는 없어요.
그치만 리스트 안의 요소를 변경할 수 있습니다. add, remove, clear 같은 조작이 가능해요~
여기서 헷갈릴 수 있는 부분이 있는데, 리스트 안의 LottoNumber도 final입니다. 그래서 내부적인 int 값은 못 바꿔요. 하지만 이건 그 객체의 값 변경을 막는 거고, 리스트에서 그 객체를 빼거나 넣는 건 리스트의 동작이라 별개입니다. 즉, 요소 자체를 삭제하거나 추가하는 것은 막을 수 없어요.
이런 동작을 막기 위해서는 어떻게 해야할까요? 학습해보시면 좋을 것 같습니다!
src/main/java/Application.java
Outdated
| final int amount = inputView.getMoney(); //돈 받기 | ||
| Money money = new Money(amount); // 돈 저장 | ||
| final int number = money.getNumber(); // 로또 뽑는 횟수 |
There was a problem hiding this comment.
맞습니다.
추가적으로
int result = a + b;
int finalResult = result * result;
int realFinalResult = finalResult / 100;
처럼 내부 계산 과정을 순서대로 모두 드러내는 것보다,
int result = calculateResult(a, b);
처럼 이 코드가 결국 무엇을 하는지가 한눈에 보이도록 표현하는 방식이 더 읽기 좋다고 생각합니다.
같은 맥락에서,
돈을 받고 → 금액을 저장하고 → 로또 구매 횟수를 계산하고 → 그 횟수만큼 로또를 생성하는 과정도
세부 단계를 바깥에 모두 펼쳐두기보다,
하나의 의미 있는 동작으로 묶어 표현할 수 있지 않을까 하는 생각이 들었습니다.
There was a problem hiding this comment.
깊게 생각해주셨군요!
실제로 기대한 동작을 하고 있다는 것을 한 눈에 볼 수 있는 방법도 있을텐데, 그것은 무엇일까요 ㅎㅎㅎㅎㅎ
| } | ||
|
|
||
| public void valueAdd(Rank rank) { | ||
| result.put(rank, result.get(rank) + 1); |
There was a problem hiding this comment.
이후 ENUM 관련 학습을 진행하면서 수정해봐도 좋을 것 같아요~
미리 학습해보셔도 좋습니다.
|
|
||
| import java.util.List; | ||
|
|
||
| public class Lottos { |
There was a problem hiding this comment.
음... 사용자가 돈을 내면 로또가 하나 이상 생성되잖아요? 그 생성부터 결과 확인까지, 여러 장의 로또를 가지고 해야 하는 일들을 생각해보세요. 기존 클래스를 삭제해도 좋습니다!
| # 테스트 케이스 | ||
|
|
||
| ```text | ||
| 구입금액을 입력해 주세요. | ||
| 5000 | ||
|
|
||
| 5개를 구매했습니다. | ||
| [3, 14, 16, 18, 22, 40] | ||
| [4, 18, 19, 30, 31, 36] | ||
| [7, 9, 20, 22, 30, 41] | ||
| [6, 18, 20, 28, 35, 39] | ||
| [5, 13, 14, 37, 44, 45] | ||
|
|
||
| 지난 주 당첨번호를 입력해 주세요. | ||
| 3, 14, 20, 22, 30, 40 | ||
|
|
||
| 당첨 통계 | ||
| --------- | ||
| 6개 일치 (2000000000)- 0개 | ||
| 5개 일치 (1500000)- 0개 | ||
| 4개 일치 (50000)- 1개 | ||
| 3개 일치 (5000)- 1개 | ||
| 총 수익률은 11.00입니다.(기준이 1이기 때문에 결과적으로 이득이라 더 뽑아도 된다는 의미임) | ||
| ``` |
There was a problem hiding this comment.
직접 입력하는 것보다 더 좋은 방법이 있을까요 ? 희창님도 매번 직접 실행해서 눈으로 확인하면 번거롭지 않으신가요?
리팩터링이 잦다보니 여쭤봅니당
페어프로그래밍을 이번에 처음하다보니 많은 시간이 소요되고 그 시간들이 정말 소중한 시간이였던 것 같습니다. 미션 해결을 하며 파트너에게 감탄하고 협업 능력을 기르고 이 미션에 대한 프로그래밍 기여도를 위해 승부욕이 좀 불타오르는 미션이였던 것 같습니다. 어떤 사람에게 코드에 대한 제 생각을 공유하는 것도 연습할 수 있었고 파트너가 제안한 코드 로직과 형식을 이해하는 시간도 너무 좋았습니다. 힘든 만큼 얻어간건 확실히 많았던 것 같습니다.
또한 원시값을 포장하는 요구사항과 일급컬렉션을 사용하라는 요구사항이 발목을 많이 잡았습니다.
하지만 파트너와 최선을 다해 요구사항을 충족시키며 코드를 만들고자 하였습니다.
완성하지 못한 부분
메서드 분리가 필요한 메서드가 많은 것 같습니다.
궁금한 부분
저희가 짠 코드가 모든 원시값을 포장했다고 볼 수 있는지 궁금합니다.
일급 컬렉션을 잘 만들고 활용했는지 궁금합니다.
하나의 메서드는 하나의 기능을 가져야하는데 책임을 너무 과하게 많이 가진 메서드가 보이시는 지 궁금합니다.
이번에는 파트너와 함께 작성했지만 자바에 아직 미숙한 점이 많고 배우는 과정이다보니 부족한 점이 많을 수 있습니다. 잘못된 점이 있다면 말씀주시고 궁금한 부분에 대한 멋진 답변 부탁드립니다! 리뷰어님!