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

[1단계 - 자동차 경주 구현] 윤생(이윤성) 미션 제출합니다. #154

Merged
merged 48 commits into from
Feb 11, 2023

Conversation

2yunseong
Copy link

No description provided.

2yunseong and others added 30 commits February 7, 2023 15:36
- @woowacourse/mission-utils 설치
Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com>
Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com>
Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com>
- 원래 콜백패턴에서 사용해 의존성이 입력 로직에 얽혀있었는데, play 메서드로 이동했다.
Copy link

@Puterism Puterism left a comment

Choose a reason for hiding this comment

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

안녕하세요 윤생 😃
이번 미션의 리뷰어를 맡게 된 체프라고 합니다. 반갑습니다!

첫번째 미션 구현하시느라 고생 많으셨어요. 전체적으로 깔끔하게 코드를 짜주셔서 떠오르는 피드백이 많지 않았네요 😅 피드백과 더불어 질문을 몇 가지 남겨놓았으니 확인 부탁드릴게요.

추가로 package-lock.json과 yarn.lock 파일이 같이 있어서 yarn과 npm을 둘 다 사용하는 것으로 보여져요. 패키지 관리자는 하나만 사용하시는 것이 좋으니 통일 부탁드릴게요! (왜 그런지도 생각해보시면 좋을 것 같네요!)

src/Car.js Outdated
Comment on lines 19 to 23
move(go) {
if (go) {
this.#position += 1;
}
}
Copy link

Choose a reason for hiding this comment

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

move라는 메소드에서는 go의 값에 따라서 this.#position의 값을 더할지 말지 결정하고 있는데요.
이렇게 되면, move라는 메소드가 다음과 같이 두 가지 역할을 하게 된다고 생각해요.

  1. go의 truthy/falsy 여부를 판별하는 역할
  2. this.#position의 숫자를 1 증가시키는 역할

move라는 메소드의 네이밍 맥락 상 this.#position의 숫자를 1 증가시키는 역할까지만 해도 충분하지 않을까 생각하는데요. 윤생의 생각은 어떠신지 궁금해요.

Copy link

Choose a reason for hiding this comment

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

위 피드백과는 별개로 go라는 네이밍만으로는 어떤 역할을 하는 파라미터를 받는 것인지 유추하기 어려울 것 같아요. 네이밍만으로 어떤 역할인지 유추할 수 있게 하려면 어떻게 이름을 짓는 게 좋을까요?

Copy link
Author

Choose a reason for hiding this comment

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

move라는 메소드의 네이밍 맥락 상 this.#position의 숫자를 1 증가시키는 역할까지만 해도 충분하지 않을까 생각하는데요. 윤생의 생각은 어떠신지 궁금해요.

  • 저 코드를 구현할 때는 go 라는 결과에 따라 자동차가 스스로 갈지 안갈지 판단하는 메서드라고 생각했습니다! 그래서 move에 함께 넣었습니다. go의 상태에 따라 갈지 안갈지는 다른 메서드에서 해주는게 좋을 것 같네요. 체프 말씀대로 move라는 메서드가 두가지 책임을 가지고 있다고 생각이 듭니다!

위 피드백과는 별개로 go라는 네이밍만으로는 어떤 역할을 하는 파라미터를 받는 것인지 유추하기 어려울 것 같아요. 네이밍만으로 어떤 역할인지 유추할 수 있게 하려면 어떻게 이름을 짓는 게 좋을까요?

  • 제 생각으로는 읽었을 때 의도가 명확하게 들어나야 될 것 같습니다! 지금은 go가 갈지 안갈지 판단할 때 필요한 값이니 이 뜻을 담을 수 있는 역할인지는 2단계 리팩토링할 때 고민해 반영해보겠습니다. 개인적인 생각으로는 먼저 책임 분리를 한 다음, 지금의 go가 하는 역할에 대해 고민해보아야 겠네요.

체프의 피드백을 읽고 고민한 부분이 있는데,go의 truthy/falsy 여부를 판별하는 역할 은 일단 Car 클래스가 가져야 된다고 생각합니다. 그 이유는 이동할지/안할지의 결정은 차 객체의 책임이라고 생각하는데요,

그러면 랜덤한 값에 따라 현재 go라는 truthy/falsy 여부를 결정하는 로직은 GameManager가 갖는다고 생각합니다. 게임에서 차에게 이동할지 말지 메세지를 보낸다고 생각하기 때문입니다.

체프는 제 의견에 대해 어떻게 생각하시나요?

Copy link

@Puterism Puterism Feb 10, 2023

Choose a reason for hiding this comment

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

저는 개인적으로 이동할지/안할지의 결정 또한 GameManager가 가지고 있어야 한다고 생각했어요. GameManager가 차를 움직이게 할지 말지를 결정할 수 있는 주체가 되는 것이 좋다고 생각했거든요. 마치 GameManager를 심판의 역할로 봤달까요?

물론 정답은 없습니다. 차 객체가 어디까지 책임을 가지게 할 것인가에 따라서 달라질 것 같아요. 결정은 윤생이 해주시면 됩니다 :)

Copy link
Author

Choose a reason for hiding this comment

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

어떤 경우가 더 나을 것인지 고민해봐야겠네요! 감사합니다 체프:D

const Console = require('./utils/Console');
const { isValidCarNames, isValidTryCount } = require('./utils/Validation');
const Car = require('./Car');
// const { pickRandomNumber } = require('./utils/RandomGenerator');
Copy link

Choose a reason for hiding this comment

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

미사용되는 코드 주석은 잘 지워주세요!

Copy link
Author

Choose a reason for hiding this comment

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

넵!!

#cars = [];

isForward() {
return RandomGenerator.pickRandomNumber() >= 4;
Copy link

Choose a reason for hiding this comment

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

전체적으로 상수화를 잘해주셨는데요.
숫자 4에 대한 상수화도 진행해주시면 좋을 것 같아요. 숫자 4는 무슨 역할을 하나요?

Copy link
Author

Choose a reason for hiding this comment

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

문제의 요구사항에서 4 이상일 경우 전진한다 를 보아, 4는 전진할지 말지 결정하는 역할을 한다고 생각하였습니다! 해당 의도에 맞게 상수화를 진행해야겠네요.

Comment on lines +43 to +48
cars.sort((a, b) => b.getPosition() - a.getPosition());
const max = cars[0].getPosition();
const winners = cars
.filter((car) => car.getPosition() === max)
.map((car) => car.getName());
return winners;
Copy link

Choose a reason for hiding this comment

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

우승자를 판정하는 로직은 sort와 filter, map을 이용해서 깔끔하게 잘 짜주신 것 같아요! 좋습니다 👍

}
}

module.exports = GameManager;
Copy link

Choose a reason for hiding this comment

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

ES6 문법으로 export하지 않은 이유가 혹시 있으셨을까요?

Copy link
Author

Choose a reason for hiding this comment

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

공통 피드백에서도 깨달았지만, 습관적으로 사용하였습니다. requiremodule.exports 와 importexport의 차이점에 대해서는 한번 알아볼 예정입니다!
혹시 체프께서 하실 말씀 있으시다면 코멘트 남겨주세요!!

const cars = gameManager.generateCars(carNames);
mockRandoms(moves);
gameManager.moveCars(cars);
expect(gameManager.judgeWinners([...cars])).toEqual(winners);
Copy link

Choose a reason for hiding this comment

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

toBe와 toEqual을 둘 다 사용해주셨는데요. toBe와 toEqual의 차이점은 무엇일까요?

Copy link
Author

Choose a reason for hiding this comment

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

toBe는 Object.is 처럼 객체의 참조(동일성)를 비교하고, toEqual은 서로 같은 정보를 가지고 있는지(동등성)을 판단하는 차이점이 있다고 생각합니다!

/* eslint-disable no-undef */
const { isValidCarNames, isValidTryCount } = require('../src/utils/Validation');

describe('Validation Test', () => {
Copy link

Choose a reason for hiding this comment

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

입력값 유효성 검사 테스트까지 진행하시다니 좋네요 👍

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다 :D

@@ -0,0 +1,10 @@
const Validation = {
isValidCarNames(carNames) {
return carNames.every((name) => name.length > 0 && name.length <= 5);
Copy link

Choose a reason for hiding this comment

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

이렇게 숫자값 그대로 코드에 사용되는 것을 매직 넘버라고 하는데요.
매직 넘버 0과 5에 대해서도 상수화를 진행해주시면 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

넵! 감사합니다. 별개로 하나 생각해본 점이 있는데요!

일단 작성한 Validation.test.js중 일부를 잠깐 가져오겠습니다!

  test.each([
    [['yunseong', 'gabriel'], false],
    [['aa', 'bb', 'cc'], true],
    [['aa', 'bb', ''], false],
    // [['aa', 'bb', '윤생이😁😁'], true], => 고민할 부분(서로게이트 쌍)
  ])('이름 유효성 검사(%s: %s)', (names, expected) => {
    expect(isValidCarNames(names)).toBe(expected);
  });

Validation.test.js에서 보시듯이, 윤생이😁😁는 사람이 느끼기에는 다섯글자입니다.
하지만, 이모티콘은 서로게이트 쌍으로, 실제로 문자열의 길이는 7이 됩니다. (1 + 1 + 1 + 2 + 2)
그런데 만약 이름이 중국어인 친구나 서로게이트 쌍으로 표현되는 문자열은 사람이 느끼기에는 5글자 이하이지만 프로그램에서는 에러가 발생하는 문제가 있다고 판단하였습니다.

그래서 이걸 어떻게 판단할지 고민하다가 미션 제출 시간이 와 일단은 넘어갔는데.. 아쉬움이 남네요.
이 아쉬움을 체프께 공유하고자 글 남겨보았습니다! 제가 아직은 깊게 찾아보진 않았는데 찾아볼 예정입니다!
혹시 체프께서도 여기 관해서 생각해볼 거리나 시도해볼 방법이 있으시다면 말씀해주시기 바랍니다!!

Choose a reason for hiding this comment

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

저도 잘 모르겠어서 조사해봤는데요. 다행히 방법이 있는 것 같네요. Intl.Segmenter에 대해서 알아보시면 좋을 것 같습니다.

@@ -0,0 +1,10 @@
const Validation = {
isValidCarNames(carNames) {
return carNames.every((name) => name.length > 0 && name.length <= 5);
Copy link

Choose a reason for hiding this comment

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

every와 some의 차이점은 무엇일까요?

Copy link
Author

Choose a reason for hiding this comment

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

every는 배열의 모든 요소가 인자로 전달한 callback에 따라 true로 평가되는지 판단하고, some은 적어도 한 요소라도 인자로 전달한 callback에 따라 true로 평가되는지 판단하는 메서드로 알고 있습니다!

Copy link
Author

@2yunseong 2yunseong left a comment

Choose a reason for hiding this comment

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

안녕하세요 체프!
 인사가 늦었네요 🚰 ·̫🚰
먼저 PR메세지를 먼저 작성했어야 했는데 그러지 못한 점 죄송합니다 ㅠㅠ 다음 번에는 주의해서 작성할께요.
많은 고민거리나 생각할 주제를 던져주셔서 너무 감사드립니다!
거기에 이어 제가 몇가지 질문이랑 답변을 남겼습니다!!
즐거운 금요일과 함께 주말도 잘 보내시길 바랍니다 :D

const cars = gameManager.generateCars(carNames);
mockRandoms(moves);
gameManager.moveCars(cars);
expect(gameManager.judgeWinners([...cars])).toEqual(winners);
Copy link
Author

Choose a reason for hiding this comment

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

toBe는 Object.is 처럼 객체의 참조(동일성)를 비교하고, toEqual은 서로 같은 정보를 가지고 있는지(동등성)을 판단하는 차이점이 있다고 생각합니다!

/* eslint-disable no-undef */
const { isValidCarNames, isValidTryCount } = require('../src/utils/Validation');

describe('Validation Test', () => {
Copy link
Author

Choose a reason for hiding this comment

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

감사합니다 :D

const Console = require('./utils/Console');
const { isValidCarNames, isValidTryCount } = require('./utils/Validation');
const Car = require('./Car');
// const { pickRandomNumber } = require('./utils/RandomGenerator');
Copy link
Author

Choose a reason for hiding this comment

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

넵!!

}
}

module.exports = GameManager;
Copy link
Author

Choose a reason for hiding this comment

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

공통 피드백에서도 깨달았지만, 습관적으로 사용하였습니다. requiremodule.exports 와 importexport의 차이점에 대해서는 한번 알아볼 예정입니다!
혹시 체프께서 하실 말씀 있으시다면 코멘트 남겨주세요!!

@@ -0,0 +1,10 @@
const Validation = {
isValidCarNames(carNames) {
return carNames.every((name) => name.length > 0 && name.length <= 5);
Copy link
Author

Choose a reason for hiding this comment

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

넵! 감사합니다. 별개로 하나 생각해본 점이 있는데요!

일단 작성한 Validation.test.js중 일부를 잠깐 가져오겠습니다!

  test.each([
    [['yunseong', 'gabriel'], false],
    [['aa', 'bb', 'cc'], true],
    [['aa', 'bb', ''], false],
    // [['aa', 'bb', '윤생이😁😁'], true], => 고민할 부분(서로게이트 쌍)
  ])('이름 유효성 검사(%s: %s)', (names, expected) => {
    expect(isValidCarNames(names)).toBe(expected);
  });

Validation.test.js에서 보시듯이, 윤생이😁😁는 사람이 느끼기에는 다섯글자입니다.
하지만, 이모티콘은 서로게이트 쌍으로, 실제로 문자열의 길이는 7이 됩니다. (1 + 1 + 1 + 2 + 2)
그런데 만약 이름이 중국어인 친구나 서로게이트 쌍으로 표현되는 문자열은 사람이 느끼기에는 5글자 이하이지만 프로그램에서는 에러가 발생하는 문제가 있다고 판단하였습니다.

그래서 이걸 어떻게 판단할지 고민하다가 미션 제출 시간이 와 일단은 넘어갔는데.. 아쉬움이 남네요.
이 아쉬움을 체프께 공유하고자 글 남겨보았습니다! 제가 아직은 깊게 찾아보진 않았는데 찾아볼 예정입니다!
혹시 체프께서도 여기 관해서 생각해볼 거리나 시도해볼 방법이 있으시다면 말씀해주시기 바랍니다!!

@@ -0,0 +1,10 @@
const Validation = {
isValidCarNames(carNames) {
return carNames.every((name) => name.length > 0 && name.length <= 5);
Copy link
Author

Choose a reason for hiding this comment

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

every는 배열의 모든 요소가 인자로 전달한 callback에 따라 true로 평가되는지 판단하고, some은 적어도 한 요소라도 인자로 전달한 callback에 따라 true로 평가되는지 판단하는 메서드로 알고 있습니다!

#cars = [];

isForward() {
return RandomGenerator.pickRandomNumber() >= 4;
Copy link
Author

Choose a reason for hiding this comment

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

문제의 요구사항에서 4 이상일 경우 전진한다 를 보아, 4는 전진할지 말지 결정하는 역할을 한다고 생각하였습니다! 해당 의도에 맞게 상수화를 진행해야겠네요.

src/Car.js Outdated
Comment on lines 19 to 23
move(go) {
if (go) {
this.#position += 1;
}
}
Copy link
Author

Choose a reason for hiding this comment

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

move라는 메소드의 네이밍 맥락 상 this.#position의 숫자를 1 증가시키는 역할까지만 해도 충분하지 않을까 생각하는데요. 윤생의 생각은 어떠신지 궁금해요.

  • 저 코드를 구현할 때는 go 라는 결과에 따라 자동차가 스스로 갈지 안갈지 판단하는 메서드라고 생각했습니다! 그래서 move에 함께 넣었습니다. go의 상태에 따라 갈지 안갈지는 다른 메서드에서 해주는게 좋을 것 같네요. 체프 말씀대로 move라는 메서드가 두가지 책임을 가지고 있다고 생각이 듭니다!

위 피드백과는 별개로 go라는 네이밍만으로는 어떤 역할을 하는 파라미터를 받는 것인지 유추하기 어려울 것 같아요. 네이밍만으로 어떤 역할인지 유추할 수 있게 하려면 어떻게 이름을 짓는 게 좋을까요?

  • 제 생각으로는 읽었을 때 의도가 명확하게 들어나야 될 것 같습니다! 지금은 go가 갈지 안갈지 판단할 때 필요한 값이니 이 뜻을 담을 수 있는 역할인지는 2단계 리팩토링할 때 고민해 반영해보겠습니다. 개인적인 생각으로는 먼저 책임 분리를 한 다음, 지금의 go가 하는 역할에 대해 고민해보아야 겠네요.

체프의 피드백을 읽고 고민한 부분이 있는데,go의 truthy/falsy 여부를 판별하는 역할 은 일단 Car 클래스가 가져야 된다고 생각합니다. 그 이유는 이동할지/안할지의 결정은 차 객체의 책임이라고 생각하는데요,

그러면 랜덤한 값에 따라 현재 go라는 truthy/falsy 여부를 결정하는 로직은 GameManager가 갖는다고 생각합니다. 게임에서 차에게 이동할지 말지 메세지를 보낸다고 생각하기 때문입니다.

체프는 제 의견에 대해 어떻게 생각하시나요?

Comment on lines +11 to +17
getName() {
return this.#name;
}

getPosition() {
return this.#position;
}
Copy link
Author

Choose a reason for hiding this comment

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

자바스크립트에서 제공하는 getter를 사용하지 않고 메서드로 만들어 사용했는데, 어느 방법이 나을까요? 저는 구현해놓고 보니 언어에서 기본적으로 제공하는 getter 기능을 사용해 보이는게 더 좋은 방법 같습니다.

Choose a reason for hiding this comment

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

저도 언어에서 제공하는 getter 기능을 사용하는 게 더 좋을 것 같다는 생각에 동의합니다 :)

Copy link
Author

Choose a reason for hiding this comment

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

답변 감사합니다~!

Copy link

@Puterism Puterism left a comment

Choose a reason for hiding this comment

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

수고 많으셨습니다! 다음 2단계에서 뵈어요~

@Puterism Puterism merged commit cfb8ddb into woowacourse:2yunseong Feb 11, 2023
@2yunseong
Copy link
Author

넵!! 감사합니다~~

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