Conversation
docs(README.md): 구현기능 목록 작성 README.md 구현기능 목록 작성 - 구현 기능목록 (구매가능 금액 최대값 SAFE INTEGER로 변경)
feat : 로또 구입금액 입력 - 로또 구입 금액 입력받기 - 로또 구입 금액 validation 체크 - 숫자(양의 정수)값을 입력했는가? - 최대값 범위 내의 정수를 입력했는가? - 1000원 단위의 값을 입력했는가?
test : 로또 구입금액 단위 테스트 - 로또 구입 금액 validation 체크에 대한 단위테스트 - 숫자(양의 정수)값을 입력했는가? - 최대값 범위 내의 정수를 입력했는가? - 1000원 단위의 값을 입력했는가?
refactor(purchasePrice) : 로또 구입 금액 유효체크 utils로 변경 - 로또 구입금액 유효체크 purchasePriceUtils 내 구현으로 변경
feat : 구매한 로또의 총 갯수를 구하고, 문구를 출력 - 구매 금액으로 구매한 로또 갯수를 구함 - 구매한 갯수를 출력
docs(README.md): 구현기능 에러 케이스 추가 (로또 번호 생성) - 로또 번호가 6개가 아닌 경우 - 로또 번호에 중복이 있는 경우
feat : 구매한 로또들의 랜덤 번호 생성 - 구매한 로또번호들의 6개 랜덤 번호를 생성 - 로또번호 6개 갯수 확인 - 로또번호 중복여부 확인 - 오름차순으로 정렬 - 구매한 로또 번호를 출력
test(Lotto) : 로또 클래스 테스트 추가 - 로또 번호가 6개인지 확인 - 로또 번호에 중복이 없는지 확인 - 로또 번호를 오름차순에 맞게 출력하는지 확인
refactor : 로또 유효성 검사 validationCheck 객체 사용 - 로또 유효성 검사 validationCheck객체 사용으로 변경 - ERROR_CODE이름 변경
- Error발생은 validate함수에서 발생시킴 - validationCheck는 boolean형 리턴으로 변경(함수명을 더 직관적으로 표현)
feat : 로또 당첨 번호를 입력 및 유효성 검증 - 양의 정수(문자, 음수 등 금지)체크 - 1~45 까지의 정수 입력 체크 - 번호 갯수 6개 체크 - 중복값 여부
test(winningNumber) : 당첨 번호 유효성 테스트 양의 정수(문자, 음수 등 금지)체크 - 1~45 까지의 정수 입력 체크 - 번호 갯수 6개 체크 - 중복값 여부
feat : 보너스 번호를 입력 - 보너스 번호 입력 - 보너스 번호 유효성 검사 - 양의 정수가 아닌 값 여부 - 1~45사이 범위에 있는지 여부 - 당첨번호와의 중복여부
test(bonusNumber) : 보너스번호 유효성 검사 - 양의 정수가 아닌 값 여부 - 1~45사이 범위에 있는지 여부 - 당첨번호와의 중복여부
fixed : 당첨번호 number array로 변경 - 당첨 번호 string array to number array
feat : 당첨 통계구하기 - index가 당첨 번호 수를 의미하는 배열을 생성 - 배열에 저장된 값은 해당 갯수로 당첨된 로또의 수
test : 당첨 통계 테스트 - index가 당첨 번호 수를 의미하는 배열을 생성 - 배열에 저장된 값은 해당 갯수로 당첨된 로또의 수 해당 배열을 제대로 생성해내는지 테스트
feat : 수익률 계산 - 당첨금의 합을 구함 - 수익률 계산 - 소수점 둘째 자리에서 반올림
test : 수익률 계산 테스트
fixed : 양의 정수 체크시 공백 오류 해결 - 양의 정수 체크시 공백 오류 문제 해결을 위해 trim추가
fixed : 테스트 형식을 위해 array출력 형식 변경 - 테스트에서 array 출력시 오류 - string으로 변경하여 출력
chore : 공백, 줄 제거 등 chore : 공백, 라인 제거, 불필요한 라이브러리 제거 등 chore : 공백, 라인 제거, 불필요한 라이브러리 제거 등
refactor : validation 파일 통합 - 여러개의 utils 중 validate 파일통합 - validationCheck -> validator로 파일명 변경
refactor : output(출력) 관련 분리 - App, lottoUtils에서 출력관련 IOHandler로 책임 분리 - InputHandler -> IOHandler로 변경
refactor : 로또 결과 계산 및 출력 부분 함수화 - 로또 결과 계산 및 수익률계산 함수 - 수익률 출력시 형식 지정 (소수점 1번째 까지 출력)
refactor : 출력은 IOHandler에서만 담당하도록 변경 - Lotto class의 출력 부분을 변경하고 IOHandler가 담당하도록 변경
refactor : default 값 사용대신 값이 있는지 체크 - default 값을 정의하지 않고, 값이 있을때만 수행하도록 변경
refactor : depth 2 제한 수정 - validator에서 depth 2를 넘어 function으로 수정
refactor(Lotto.js) : private method로 변경 - 클래스 내부에서만 사용되어야 하는 함수 private으로 변경
MyungJiwoo
left a comment
There was a problem hiding this comment.
리뷰가 좀 부족할 수 있지만 최선을 다해봤습니다..!!
3주차 미션도 고생 많으셨습니다! 🍀
| #validate(numbers) { | ||
| if (!validator.isCorrectSize(numbers, LOTTO.SIZE)) { | ||
| throw new Error(ERROR_CODE.SIZE_OUT_OF_RANGE(LOTTO.SIZE)); | ||
| } | ||
| if (validator.hasDuplicates(numbers)) { | ||
| throw new Error(ERROR_CODE.NUMBER_DUPLICATE) | ||
| } | ||
| } |
There was a problem hiding this comment.
numbers를 여기에서 검사하는 것도 좋지만 로또 번호 검사는 동일하다 생각해서, 직접 생성하신 validation/validator에서 을 적용시키는 것은 어떨까요?
| getPrize(matchNumber) { | ||
| switch (matchNumber) { | ||
| case 7: | ||
| return LOTTO.FIRST_PRIZE | ||
| case 6: | ||
| return LOTTO.SECOND_PRIZE | ||
| case 5: | ||
| return LOTTO.THIRD_PRIZE | ||
| case 4: | ||
| return LOTTO.FOURTH_PRIZE | ||
| case 3: | ||
| return LOTTO.FIFTH_PRIZE | ||
| default: | ||
| return 0 | ||
| } | ||
| }, |
There was a problem hiding this comment.
matchNumber 값을 키로 하는 객체를 만들고, 해당 객체에서 값을 조회하는 방식을 사용하면 조금 더 간결한 코드 작성이 가능할 것 같아요!
const prizeMap = {
7: LOTTO.FIRST_PRIZE,
6: LOTTO.SECOND_PRIZE,
5: LOTTO.THIRD_PRIZE,
4: LOTTO.FOURTH_PRIZE,
3: LOTTO.FIFTH_PRIZE,
};
const prize = prizeMap[matchNumber] || 0;
| export const LOTTO = { | ||
| SIZE: 6, | ||
| MIN_NUMBER: 1, | ||
| MAX_NUMBER: 45, | ||
| FIRST_PRIZE: 2000000000, | ||
| SECOND_PRIZE: 30000000, | ||
| THIRD_PRIZE: 1500000, | ||
| FOURTH_PRIZE: 50000, | ||
| FIFTH_PRIZE: 5000, | ||
| } |
There was a problem hiding this comment.
내부 프로퍼티는 외부에서 수정될 수 있기 때문에 Object.freeze를 사용해 객체를 수정하지 못하도록 접근 제어하는 것은 어떨까요?
There was a problem hiding this comment.
다양한 테스트 케이스가 예외 상황을 많이 고민하신게 느껴져요! 고생 많으셨습니다 👏🏻
MinSungJe
left a comment
There was a problem hiding this comment.
안녕하세요! 코드 너무 잘봤습니다.
여러 경우에 대해 테스트 코드를 이용해 철저하게 검사된 코드라고 생각이 들었습니다.👍
코드에 대한 전반적인 리뷰를 남깁니다.
어느덧 프리코스가 끝나가고 있네요, 마지막 제출까지 화이팅입니다!😄😄
| describe("당첨 케이스 테스트", () => { | ||
| test("1등 당첨 케이스", () => { | ||
| const lottos = [ | ||
| new Lotto([1, 3, 5, 8, 11, 38]) | ||
| ] | ||
| const winningNumbers = [1, 3, 5, 8, 11, 38] | ||
| const bonusNumber = 39 | ||
|
|
||
| const lottoGame = new LottoGame(winningNumbers, bonusNumber, lottos); | ||
| const lottoResult = [0, 0, 0, 0, 0, 0, 0, 1] //배열의 index는 일치하는 갯수를 위미( but, 6은 2등(5개 + 보너스)/ 7은 1등) | ||
|
|
||
| expect( | ||
| lottoGame.getLottoMatchResultArray() | ||
| ).toStrictEqual(lottoResult); | ||
| }); | ||
|
|
||
| test("2등 당첨 케이스", () => { | ||
| const lottos = [ | ||
| new Lotto([1, 3, 5, 8, 11, 39]) | ||
| ] | ||
| const winningNumbers = [1, 3, 5, 8, 11, 38] | ||
| const bonusNumber = 39 | ||
|
|
||
| const lottoGame = new LottoGame(winningNumbers, bonusNumber, lottos); | ||
|
|
||
| const lottoResult = [0, 0, 0, 0, 0, 0, 1, 0] //배열의 index는 일치하는 갯수를 위미( but, 6은 2등(5개 + 보너스)/ 7은 1등) | ||
|
|
||
| expect( | ||
| lottoGame.getLottoMatchResultArray() | ||
| ).toStrictEqual(lottoResult); | ||
| }); | ||
|
|
||
| test("3등 당첨 케이스", () => { | ||
| const lottos = [ | ||
| new Lotto([1, 3, 5, 8, 11, 39]) | ||
| ] | ||
| const winningNumbers = [1, 3, 5, 8, 11, 38] | ||
| const bonusNumber = 40 | ||
|
|
||
| const lottoGame = new LottoGame(winningNumbers, bonusNumber, lottos); | ||
|
|
||
| const lottoResult = [0, 0, 0, 0, 0, 1, 0, 0] //배열의 index는 일치하는 갯수를 위미( but, 6은 2등(5개 + 보너스)/ 7은 1등) | ||
|
|
||
| expect( | ||
| lottoGame.getLottoMatchResultArray() | ||
| ).toStrictEqual(lottoResult); | ||
| }); | ||
|
|
||
| test("4등 당첨 케이스", () => { | ||
| const lottos = [ | ||
| new Lotto([1, 3, 5, 8, 11, 39]) | ||
| ] | ||
| const winningNumbers = [1, 3, 5, 8, 14, 38] | ||
| const bonusNumber = 40 | ||
|
|
||
| const lottoGame = new LottoGame(winningNumbers, bonusNumber, lottos); | ||
|
|
||
| const lottoResult = [0, 0, 0, 0, 1, 0, 0, 0] //배열의 index는 일치하는 갯수를 위미( but, 6은 2등(5개 + 보너스)/ 7은 1등) | ||
|
|
||
| expect( | ||
| lottoGame.getLottoMatchResultArray() | ||
| ).toStrictEqual(lottoResult); | ||
| }); | ||
|
|
||
| test("5등 당첨 케이스", () => { | ||
| const lottos = [ | ||
| new Lotto([1, 3, 5, 8, 11, 39]) | ||
| ] | ||
| const winningNumbers = [1, 3, 5, 10, 14, 38] | ||
| const bonusNumber = 40 | ||
|
|
||
| const lottoGame = new LottoGame(winningNumbers, bonusNumber, lottos); | ||
|
|
||
| const lottoResult = [0, 0, 0, 1, 0, 0, 0, 0] //배열의 index는 일치하는 갯수를 위미( but, 6은 2등(5개 + 보너스)/ 7은 1등) | ||
|
|
||
| expect( | ||
| lottoGame.getLottoMatchResultArray() | ||
| ).toStrictEqual(lottoResult); | ||
| }); | ||
|
|
||
| test("0개 일치 케이스", () => { | ||
| const lottos = [ | ||
| new Lotto([1, 3, 5, 8, 11, 39]) | ||
| ] | ||
| const winningNumbers = [2, 4, 6, 10, 14, 38] | ||
| const bonusNumber = 40 | ||
|
|
||
| const lottoGame = new LottoGame(winningNumbers, bonusNumber, lottos); | ||
|
|
||
| const lottoResult = [1, 0, 0, 0, 0, 0, 0, 0] //배열의 index는 일치하는 갯수를 위미( but, 6은 2등(5개 + 보너스)/ 7은 1등) | ||
|
|
||
| expect( | ||
| lottoGame.getLottoMatchResultArray() | ||
| ).toStrictEqual(lottoResult); | ||
| }); |
There was a problem hiding this comment.
당첨 케이스의 n개 일치 케이스는 반복되는 부분이 많아, test.each()를 이용하면 테스트 코드의 양을 줄일 수 있을 것 같아요!
또 winningNumbers와 bonusNumber가 다 같아보이는데, 이 경우에는 test() 안보다 describe()안에 작성하면 중복을 줄일 수 있어보이네요! 😊
| if (!validator.isPositiveNumber(purchasePrice)) | ||
| throw new Error(ERROR_CODE.NOT_POSITIVE_NUMBER); | ||
| if (!validator.isInRange(purchasePrice)) { | ||
| throw new Error(ERROR_CODE.OUT_OF_RANGE(1, Number.MAX_SAFE_INTEGER)); |
There was a problem hiding this comment.
Number.MAX_SAFE_INTEGER가 Number에서 제공하는 가장 큰 integer 값인가 보네요🤔
max 값을 정할 때 유용할 것 같아요!!
| calculateTotalPrize() { | ||
| let totalPrize = 0; | ||
| this.getLottoMatchResultArray().forEach((amount, index) => { | ||
| totalPrize += amount * lottoUtils.getPrize(index); | ||
| }) | ||
| return totalPrize; | ||
| } |
There was a problem hiding this comment.
이 코드는 reduce()를 이용해 간단하게 만들 수 있을 것 같아요! reduce는 어떤 배열을 이용해 특정한 값을 계산하고 싶을 때 사용하는 함수입니다🙂
calculateTotalPrize() {
return this.getLottoMatchResultArray().reduce((totalPrize, amount, index) =>
totalPrize + amount * lottoUtils.getPrize(index), 0);
}
[3주차] 로또
1. 구현할 기능 목록
1. 입력값 받기 : 로또 구입 금액 입력받기
2. 구매한 로또의 총 갯수를 구하고, 문구를 출력한다.
3. 구매한 로또들의 랜덤 번호 생성
4. 당첨 번호를 입력받는다
5. 보너스 번호를 입력받는다.
6. 당첨 통계를 구한다
7. 수익률을 계산한다
2. 예외 케이스
1. 로또 구입 금액 입력받기
3. 구매한 로또들의 랜덤번호 생성
4. 로또 당첨 번호 입력
5. 보너스 번호 입력
3. 고민한 부분
특히, validation Check를 꼼꼼하게 하지 못했다고 생각해서, 검사하는 부분 및 순서에 시간을 많이 사용하였습니다. 또한, 해당 부분을 중점으로 unit test를 좀 더 꼼꼼하게 작성하였습니다.
이번 과제는 구현하면서 세세한 부분이 생각보다 많아, 제가 생각한 것보다 코드를 깔끔하게 작성하기 어려웠습니다.
또한, 코드와 함수가 많아지니 책임의 분리가 어려웠습니다. 부족한 코드지만 많은 피드백 부탁드립니다.
##4. 클래스 방식 추가
[로또] 이유정 미션 제출합니다. #96 (comment)