-
Notifications
You must be signed in to change notification settings - Fork 168
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
[1단계 - 콘솔 기반 로또 게임] 센트(김영우) 미션 제출합니다. #174
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요
@kyw0716 👋
반갑습니다.
저는 리뷰어 포코라고 합니다!
소소한 리뷰
- eslint 강제 주석이 너무 많습니다.
- 린트가 동작하고 있나요? 일관성 없이 작성된 포맷팅이 계속 발견됩니다.
- 불필요하고 과한 분리들이 반복됩니다
- 함수 혹은 메서드가 적절히 분리되지 않아 여러 일을 반복합니다.
- 예외 처리 방법이.. 애매한 것 같아요. 더 좋은 방법을 고민해보세요!
Q&A
Q1. 랜덤한 요소에 대한 테스트를 어떻게 진행하는 것이 좋을지 궁금합니다!
스택오버플로우에 랜덤 테스트에 대해 검색해보시면 정말 훌륭한 의견들을 볼 수 있답니다.
한번 참고해보세요. 정말 재미있답니다.
Q2. 입력값을 저장하기 위해서만 사용하는 클래스를 사용했는데 이러한 방식이 맞는지 궁금합니다!
의도에 동의가 되는 사용 방식은 아닌 것 같습니다.
저도 설명을 들어서 이제서야 이해했고 코드를 다시 봤지만.. 그런 의도대로 작성된 코드가 맞나? 의문이 드네요 😢
몇가지 코멘트 리뷰도 남겼으니 참고해보세요!
@@ -1,11 +1,44 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OMG... 😱
프론트엔드 개발자라면 다양한 확장자를 주의해서 다뤄야합니다.
HTML.. CSS... JS 모두 주석 사용 방법도 다른데요. JSON은 설정 파일이기때문에 더 주의해야합니다.
- JSON은 누가? 왜? 무엇을 대체하기 위해 만들어졌을까요?
- JSON에서는 주석이 가능할까요?
- 현재 이 JSON을 파싱해보면 잘 동작할까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON에 주석이 지원되지 않는다는 것을 모르고 그동안 사용했던 것 같네요 😭😭
수정한 커밋: bda4f74
추가로 주신 질문들을 보고 학습 한 내용입니다!
Q: JSON은 누가? 왜? 무엇을 대체하기 위해 만들어졌을까요?
A: XML로 정보를 주고 받을 때 헤더와 태그 등 여러 요소들로 인해 가독성이 떨어지고, 쓸데 없는 용량을 잡아먹는다는 단점을 갖고 있어 이를 대체하기 위해 더글라스 크록포드에 의해 만들어졌습니다!
Q: JSON에서는 주석이 가능할까요?
A: JSON에는 주석을 지원하지 않아 설정파일에 주로 사용됩니다! (이걸 몰랐네요 ㅠㅠㅠ)
Q: 현재 이 JSON을 파싱해보면 잘 동작할까요?
A:
const json = '{"hi": true //주석}';
const obj = JSON.parse(json);
console.log(obj);
주석이 있을 때 파싱이 이루어질 수 있는지 판별해보고자 간단한 예시 코드를 실행시켜 보았더니 오류가 발생하는 것을 확인할 수 있었습니다😭
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 완벽합니다!!
JSON
에게 어쩌면 주석조차도 데이터가 아닐까요? 후후
@@ -0,0 +1,15 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기도..ㅠㅠ주석이..
__tests__/Lotto.test.js
Outdated
|
||
const profit = calculateProfit(lotto.getRank()); | ||
|
||
expect(profit).toBe(expectedProfit); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expectedProfit
이 아니라 다른 네이밍으로 가야 기대하는 테스트 결과물과 비교하지 않을까요?
expect()
에 이미 의미가 포함되어 있으니까요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
계산 되어져 나온 결과라는 의미를 담고자 네이밍을 expected
=> caculated
로 변경했습니다!
수정한 커밋: 2636e6b
__tests__/Lottos.test.js
Outdated
const bonusNumber = 7; | ||
|
||
lottos.calculateAllRanks(winningNumbers, bonusNumber); | ||
//console.log(lottos.#calculateProfitRate(), lottos.getAllRanks()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
console.log
를 다 지웠다고 생각했는데 남아있는게 있었네요😭😭 바로 수정했습니다!
수정한 커밋: 53a430a
@@ -0,0 +1,64 @@ | |||
# 기능 목록 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
체크박스가 없는 것을 보면.. 다 했다고 볼 수 있는 것일까요?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
체크박스 추가했습니다! 진행상황을 중간중간 체크하기 위해서 체크박스를 쓰는 것이 좋을 것 같네요!! 감사합니다😀😀
수정된 커밋: c308849
src/domain/model/Lottos.js
Outdated
} | ||
|
||
#calculateProfit() { | ||
const initialValue = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
음 따로 빼낼 이유가 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
따로 빼지 않는 방식으로 수정 완료 했습니다!
수정한 커밋: 01c60f5
src/domain/model/Lottos.js
Outdated
const initialValue = 0; | ||
|
||
return this.#ranks.reduce((profit, rankCount, index) => { | ||
return profit + rankCount * profitByRank[index]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
연산 순서를 명시하는게 좋지 않을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정 완료했습니다!
수정한 커밋: d24cb62
src/domain/model/Lotto.js
Outdated
} | ||
|
||
#setRankTwoOrThree(bonusNumber) { | ||
this.#rank = this.#numbers.includes(bonusNumber) ? 2 : 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
열심히 상수를 만드시던데 2, 3을 너무 날로 작성하시는군요! 휴먼 에러가 발생되지 않을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
상수를 만드는 이유 중에 하드코딩된 값의 역할을 명확히 하기 위함도 있다는 것을 이 부분에서 생각하지 못했던거 같습니다. 하드코딩된 값 모두 상수처리하여 수정 완료했습니다!!
수정한 커밋: 7485474
winningNumbers: undefined, | ||
bonusNumber: undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
음 숫자를 다루는데 초기 값을 undefined
로 사용할때 문제는 없으신가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WinningNumbers
와 BonusNumber
클래스를 컨트롤러에서 사용하기 때문에 생성된 로또들에 대한 정보까지 합하면 인스턴스 변수를 3개 이상 사용하지 말라는 요구사항을 지키지 못해 그걸 통합하고자 위와 같은 코드가 탄생하게 됐습니다...😭😭
저렇게 하는 방식보단 WinningLotto
로 한꺼번에 두 값들을 가지고 있게 리팩터링 하면 어떨까 싶어 수정해봤습니다!!
수정한 커밋: 22e668a
|
||
#setRank(correctNumberCount, bonusNumber) { | ||
if (correctNumberCount === correctCountPerRank.SECOND_RANK) | ||
return this.#setRankTwoOrThree(bonusNumber); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
음 굳이 분리할 이유가 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
depth를 1까지만 허용한다는 요구사항과 함수의 길이를 10으로 제한한다는 요구사항을 충족하려다 최대한 생각한 방식이 저런 방식이었습니다😭😭
before: 하나의 랜덤 값을 생성하고, 빈 배열에 중복되지 않게 그 값을 채워넣고 생성하는 것을 반복하여 랜덤 로또 번호를 생성 after: 최소 ~ 최대까지의 숫자를 전부 포함하는 배열을 생성하여 랜덤하게 섞은 후 로또 번호의 개수만큼 잘라서 반환하는 방식으로 로또 번호 생성
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드를 상당 부분 개선하셨네요!
아래의 항목만 점검해보시면 좋겠습니다!
- 사용자의 애플리케이션 사용 흐름을 고려한 TDD
- 불필요한 추상화 기준
- 에러 처리에 대한 고민
- 네이밍 동사 위치 재점검
- 과한 코드 라인 축소 및 불안한 포매팅 점검
물론 이외에도 아쉬움이 많이 들 수 있겠지만 차근차근 2단계까지 함께 진행해보아요
그럼 2단계에서 뵙겠습니다!
@@ -1,11 +1,44 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 완벽합니다!!
JSON
에게 어쩌면 주석조차도 데이터가 아닐까요? 후후
"es6": true, | ||
"node": true | ||
}, | ||
"parserOptions": { | ||
"ecmaVersion": "latest" | ||
}, | ||
"extends": ["eslint:recommended", "plugin:prettier/recommended"] | ||
"extends": ["airbnb", "plugin:prettier/recommended"], | ||
"rules": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5기는 ESLint
경쟁이 한참인가보군요 ㅋㅋ
"source.fixAll.eslint": true | ||
}, | ||
"eslint.alwaysShowStatus": true, | ||
"prettier.disableLanguages": ["js"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아니 이것은... 👀
}, | ||
"eslint.alwaysShowStatus": true, | ||
"prettier.disableLanguages": ["js"], | ||
"files.autoSave": "onFocusChange" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"[javascript]": {
"editor.formatOnSave": true
},
위의 설정이랑 겹치지 않을까요?
/*eslint-disable */ | ||
const Lottos = require("../src/domain/model/Lottos"); | ||
|
||
describe("Lottos 테스트", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아주 깔끔한 테스트군요 ㅎㅎ
GWT 까지 좋아요
const lottos = []; | ||
|
||
while (lottos.length < lottoCount) { | ||
lottos.push(randomNumberGenerator.generateLottoNumbers()); | ||
} | ||
|
||
this.#lottos = lottos.map((lottoNumber) => new Lotto(lottoNumber)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
루프를 한번에 할 수 있지 않을까요?
불필요한 연산같기도 하고 오히려 좋은 가독성은 좋기도하고 애매하네요
lotto.calculateRank(winningNumbers, bonusNumber); | ||
|
||
this.#calculateRank(lotto.getRank()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
처음 협업하는 입장에서 아래와 같은 코드가 하나의 함수에 포함되어있다면 맥락 파악이 잘 될까요?
lotto.calculateRank()
& this.#calculateRank()
} | ||
|
||
#calculateRank(lottoRank) { | ||
if (lottoRank === undefined) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
에러를 던질 필요는 없은걸까요?
const profitRate = this.#calculateProfitRate(); | ||
return profitRate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
바로 반환해도 될 것 같고.. 애초에 불필요한 추상화로 느껴지기도 하네요!
const { errorMessage } = require('../constants/constants'); | ||
const validator = require('../domain/validation/validator'); | ||
|
||
const exception = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사실 에러처리라는게 정말 어려운 부분이기도 합니다.
에러에 대한 알림을 받는 대상자가 누구인가 또한 에러를 던지고 처리하는 레이어는 어디인가를 고민해보시면 좋아요.
하지만 음.. 이런 활용 방법이 효용성이 있다라는 공감대는 들지 않는 편이네요
- 일단은 언어에서 기본적으로 제공해주는
try~catch
를 적극 활용하셨으면 좋겠습니다. - 에러를 주로 받는 레이어는 어디인가
- 에러를 주로 던지는 레이어는 어디인가
- 에러를 받아야하는 대상자는 누구인가 (사용자, 동료 개발자 혹은 나 자신)
또한 TDZ 로 인한 레퍼런스 에러 수신에 대해서도 고민해보시면 좋아요
안녕하세요 포코!! 이번에 제로와 함께 콘솔 기반 로또 게임을 구현한 센트 입니다😀😀
제가 구현한 모델들은 다음과 같이 추상화했습니다!
1️⃣ Lotto 클래스
📝필드
#numbers
: 로또 번호#rank
: 로또 등수🛠️ 메서드
getNumbers()
: 로또 번호 반환 기능getRank()
: 로또 등수 반환 기능caculateRank()
: 로또 등수 계산 기능 (등수를 계산하여 rank 필드 값을 채워줌)2️⃣ Lottos 클래스
📝필드
#lottos
: 생성된 로또 인스턴스들을 담는 배열#ranks
: 1등부터 5등까지 각 등수에 해당하는 로또의 개수를 담는 배열🛠️ 메서드
getLottos()
: 로또 인스턴스들이 담겨 있는 배열 반환 기능getAllRanks()
: 각 등수에 해당하는 로또들의 개수를 담은 배열 반환 기능getProfitRate()
: 수익률을 반환하는 기능caculateAllRanks()
: 각 로또들의 등수를 계산하여#ranks
필드를 채우는 기능3️⃣ WinningNumbers 클래스
📝필드
#numbers
: 당첨 번호🛠️ 메서드
getNumbers()
: 당첨 번호 반환 기능4️⃣ BonusNumber 클래스
📝필드
#number
: 보너스 번호🛠️ 메서드
getNumber()
: 보너스 번호 반환 기능1️⃣ 랜덤한 요소에 대한 테스트를 어떻게 진행하는 것이 좋을지 궁금합니다!
이번 미션을 진행하면서
Lottos
클래스를 만들어 구입 금액이 입력되면 랜덤숫자를 만들어Lotto
인스턴스를 생성해 저장하는 방식으로 구현을 했었습니다. 이때 TDD를 적용해보고자 했는데Lottos
클래스를 테스트 하는데 많은 어려움이 있었습니다. 혹시 이러한 경우에 어떤 방식을 사용하여 테스트를 진행하는 것이 좋을지 궁금합니다!!2️⃣ 입력값을 저장하기 위해서만 사용하는 클래스를 사용했는데 이러한 방식이 맞는지 궁금합니다!
setter를 사용해 객체 내부의 값을 변경하는 일이 없도록 하기 위해서 입력값을 저장하고자
WinningNumbers
,BonusNumber
클래스를 사용했었습니다. 이때 저 두 클래스의 존재 의미가 오직 입력값을 저장하기 위해서고, 다른 기능은 수행하지 않기 때문에 혹시 이러한 경우에 사용하는 다른 방식이 있을까 궁금합니다!!!