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

[자동차 경주] 조승우 미션 제출합니다. #350

Open
wants to merge 63 commits into
base: main
Choose a base branch
from

Conversation

seungineer
Copy link

@seungineer seungineer commented Oct 28, 2024

javascript-racingcar-precourse

프리코스 2주 차 미션 - 자동차 경주

스스로 정한 규칙

🚸 입력 예시에 따른 에러 처리 결과는 README.md 파일에서 확인하실 수 있습니다.

  • 입력된 이름은 두 개 이상이어야 한다.
    • 한 개일 때는 '경주'가 성립하지 않기 때문이다.
  • 입력된 이름은 ‘공백을 포함한’ 문자열의 길이가 5 이하인 경우 해당 문자열이 그대로 이름이 된다.
    • 입력된 공백을 임의로 삭제하지 않는다.
    • ex) 도 길이가 5인 이름이라고 할 수 있다.
    • ex) 은 길이가 다르기에 서로 다른 이름이다.
  • 중복된 이름은 순서대로 출력된다.
    • '실행 결과'가 항상 출력되므로 사용자가 분간할 수 있기 때문이다.
  • 이동 횟수가 0회인 경우 경주가 이루어지지 않기에 error 처리한다.
  • 이름의 개수(n)에 시도 횟수(k)를 곱한 값은 $10^7$ 미만이어야 한다.
    • 프로그램 연산의 시간 복잡도 $O(n*k)$를 고려한다.

구현 기능 목록

  • 사용자 입력 요청 메시지 출력하기
    • 경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)\n
      • 사용자로부터 n대 자동차의 이름 입력 받기
    • 시도할 횟수는 몇 회인가요?
      • 사용자로부터 이동 횟수(k) 입력받기
  • 사용자 입력 검증 하기
    • 한 개의 이름이 문자열의 길이가 5가 넘지 않으며, 쉼표(,)로 구분되는지 검증
    • 시도 횟수 k는 1 이상의 정수만 입력
  • 게임 내에서 자동차를 객체로 관리하기
  • k회 반복하며 각 자동차에 대해 전진 또는 정지 결정
    • 전진: 0과 9 사이 랜덤한 수 중 4 이상이 추출될 경우
    • 정지: 0과 9 사이 랜덤한 수 중 4 미만이 추출될 경우
  • 반복 회차마다 실행 결과 출력하기
  • 가장 많이 전진한 자동차를 최종 우승자로 선정 (여러 대일 수 있음) 하여 출력하기
    • 최종 우승자 : pobi, jun

구현에 집중한 부분

  • 폴더 구조

    • 1주 차 코드 리뷰 피드백을 반영하여 기능에 맞는 폴더에 각 파일을 위치시켰습니다.
  • 클래스 분리

    • Game 클래스 내부를 '각 라운드를 관리하는 RoundManager', '자동차 객체를 할당 및 분배하는 CarAllocator'로 분리하였습니다.
    • Car 객체는 '이동한 거리', '전진 기능', '자신의 이름과 이동한 거리를 반환하는 기능'을 담당합니다.
  • 에러 메시지 구체화

    • 에러 메시지 내에 어떤 값이 입력되었고, 어떤 값을 입력하는 것으로 수정해야 하는지 구체적으로 반영하였습니다.
  • Javascript API 사용

    • if ... else, 반복문을 줄이기 위해 Math.max(), filter(), map(), forEach()등을 사용하였습니다.

폴더 구조

src
 ┣ components
 ┃ ┣ Car.js // 자동차 객체 관리 컴포넌트
 ┃ ┣ CarAllocator.js // 자동차 할당 및 분배 정보 처리 컴포넌트
 ┃ ┣ Game.js // 게임 진행과 상태를 관리하는 컴포넌트
 ┃ ┗ RoundManager.js // 게임 라우든 관리 및 진행 순서를 담당하는 컴포넌트
 ┣ resources
 ┃ ┣ Constants.js // App 전반에 사용되는 상수 정의한 파일
 ┃ ┣ ErrorMessage.js // Error 발생 시 출력 메시지를 정의한 파일
 ┃ ┣ RegularExpression.js // App에서 사용하는 정규표현식을 정의한 파일
 ┃ ┗ Rules.js // 게임 관련 규칙을 정의한 파일
 ┣ utils
 ┃ ┣ io
 ┃ ┃ ┣ Input.js // 사용자 입력을 처리하는 기능을 담은 유틸리티 파일
 ┃ ┃ ┗ Output.js // 출력 처리 기능을 담은 유틸리티 파일
 ┃ ┗ validation
 ┃ ┃ ┣ validateNames.js // 자동차 이름 관련 입력 유효성 검사를 수행하는 유틸리티 파일
 ┃ ┃ ┣ validateRepetitionString.js // 시도 횟수 입력 유효성 검사를 수행하는 유틸리티 파일
 ┃ ┃ ┗ validateTimeComplexity.js // 사용자 입력의 시간 복잡도 검사를 수행하는 유틸리티 파일
 ┣ App.js
 ┗ index.js

Discussion

  • RoundManager에서 Car 객체 배열을 받아 중간 결과 출력에 필요한 값을 반환합니다. 이 부분으로 인해 Car가 완전히 분리되지 않은 것 같아서 어떻게 수정할지 고민되었습니다.. 💭
  • Game 클래스 내에서 private fileds로 Car 객체를 관리하였습니다. Car 객체를 Game과 더욱 분리할 수 있는 구조가 있을지 궁금합니다.
  • 주석이 거의 달려 있지 않습니다. 주석이 필요할 것 같은데 없는 곳이 있다면 말씀해주시면 감사하겠습니다.

과제 진행 요구 사항에 따라 기능 구현 전 기능 목록을 추가한다.
과제 요구 사항 관련 스스로 정한 규칙을 추가한다.
- README.md 파일
자동차 이름 및 게임 반복 횟수를 두 번의 질문을 통해 입력 받는다.
중복된 이름 처리 규칙을 추가한다.
공백을 포함하는 것과 관련한 예시를 추가한다.
입력 받은 names, repetitionNumber를 Games에 반영하여 생성한다.
구현 기능 목록 중에서 게임 클래스 내에 자동차를 객체로 관리 하는 항목을 추가한다.
쉼표(,)를 기준으로 입력 받은 자동차 이름 문자열을 split 하여 자동차 이름을 배열로 관리한다.
각각의 이름을 갖는 자동차 객체를 생성하여 배열로 관리한다.
입력 받은 name으로 자동차 객체에 name을 할당하고, 객체의 현재 이동 거리가 0이 되도록 생성한다.
inputHandler에서 반환하는 반복 횟수 관련 변수명을 수정하여 횟수 정보임에도 여전히 문자열임을 나타낸다.
- repetitionNumber -> repetitionString
play 메서드를 통해 반복 횟수 만큼 game Round가 반복적으로 진행된다.
CARS_LIST의 모든 car에 대해 전진 가능 여부를 판단하고, 가능할 경우 전진하는 메서드이다.
0과 9 사이의 무작위 수를 추출한 결과 값이 4 이상인지 판단하는 메서드를 추가한다.
자동차 객체 내에서 속성의 currentDistance를 증가시키는 메서드이다.
매 Round가 종료된 직후 Round 결과를 출력한다.
car 객체 중 currentDistance 값이 가장 큰 car의 name을 배열로 반환하는 기능을 추가한다.
입출력 요구 사항에 맞게 최종 우승자를 출력한다.
반복문 내 두 개의 if 문으로 인해 가독성이 저하되어  filter, map으로 리팩터링한다.
names, repetitionString에 대해 처리 가능한 형식인지 확인한다.
모든 구현 기능 목록이 완료 표시 된다.
입력된 이름의 개수에 대한 규칙을 추가한다.
기존 한 개의 이름이 입력되어도 되던 것을 두 개 이상이 이름이 입력되어야 validation pass 되도록 정규 표현식을 수정한다.
입력된 자동차 이름과 시도 횟수 관련 검증 단계에서 처리해야 하는 예외 목록을 추가한다.
스스로 정한 규칙, 구현 기능 목록에 존재하는 어색한 문장을 명확하게 다듬는다.
주석을 의미가 명확하게 수정하고,
에러 메시지의 문장을 개선한다.
예외 처리한 음수와 실수는 아래의 형태를 갖는다.
- 음수인 경우는 '-숫자' 형태이다.
- 실수인 경우는 '숫자.숫자' 형태이다.
에러 메시지에서 사용자가 입력한 메시지를 언급하는 부분을 추가한다.
Test 이름을 명확하게 한다.
- 쉼표(,)로 끝나는 이름 문자열 관련 에러 메시지 : INVALID_NAME_FORMAT에서 COMMA_ENDING_NAMES으로 수정한다.
- 0이 입력되는 경우 관련 에러 메시지 : GREATER_THAN_ZERO에서 ZERO_NUMBER_INPUT으로 수정한다.
- 반복 횟수에 숫자 이외 문자가 포함되는 경우 관련 에러 메시지 : INVALID_NUMBER_INPUT에서 INPUT_CONTAIN_CHARACTER으로 수정한다.
validateNames.js 및 validateRepetitionString.js를 테스트 한다.
Test 코드 작성 시 이동 가능 여부를 Car 객체 별로 구분하여 지정해야 하기에 기존 정적으로 선언되었던 것을 인스턴스 속성에 추가한다.
입력된 이름의 수와 게임 반복 횟수를 곱하여 1e7을 초과할 경우 예외 처리한다.
기존 Components 폴더에 위치하던 입출력 모듈을 util 폴더로 분리한다.
game 클래스 리팩터링에 따른 중간 결과 출력 방식을 변경한다.
Game 클래스 내의 기능을 CarAllocator 클래스로 분리함에 따라 테스트 코드도 함께 분리한다.
기존 유효한 시간 복잡도 초과인 경우 에러 처리되던 것을 이상인 경우 에러 처리되도록 수정한다.
Copy link

@nerdchanii nerdchanii left a comment

Choose a reason for hiding this comment

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

승우님 고생하셨습니다!:) 시간복잡도를 고려한게 인상깊었어요! 저는 음수는 깜빡했는데..! ㅋㅋㅋㅋ음수도 잘 처리하셨군요 👍🏻👍🏻

@@ -0,0 +1,34 @@
import Car from '../src/components/Car';
import Rules from '../src/resources/Rules';

Choose a reason for hiding this comment

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

import할떄 RULES로 선언하셨으면 상수로 인식하기더 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

오! 정말 그런 것 같아요.
변하지 않는 상수라는 뜻이 잘 내포되는 것 같습니당 👍

Comment on lines +5 to +10
static async get() {
const names = await Console.readLineAsync(InputView.INPUT_CAR_NAMES_PROMPT);
const repetitionString = await Console.readLineAsync(
InputView.INPUT_REPETITION_COUNT_PROMPT,
);
return { names, repetitionString };

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.

Input은 시도할 기회를 주려고 합니다 ㅎㅎ. 그러나 Validator에서 Error처리가 되죠!

utilsInput은 입력을 받아들이는 역할만 하기 때문입니다.

const resultNames = winners
.map((name) => name)
.join(OutputView.WINNER_NAME_SEPARATOR);
Console.print(OutputView.WINNER_PRINT_PREFIX + resultNames);

Choose a reason for hiding this comment

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

+로 문자열을 합치기보단 templateLiteral을 사용하는 건 어떨까요?!:)
6.3

Copy link
Author

Choose a reason for hiding this comment

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

헉.. 습관적으로 +로 붙여 버렸습니다.. 습관이 무섭네요 😅

피드백 감사합니다!

Comment on lines +32 to +36
validateNegativeNumber(repetitionString);
validateDecimalNumber(repetitionString);
validateZeroNumber(repetitionString);
validateZeroStarting(repetitionString);
validateNotNumber(repetitionString);

Choose a reason for hiding this comment

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

함수들을 배열로 만들어서 돌려도 좋을것 같아요!
[validateNegativeNumber, validateDecimalNumber, ...number].forEach(fn => fn(repetitionString));이런식이 되도록이여!

Copy link
Author

Choose a reason for hiding this comment

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

"validate", "repetition"이라는 단어가 반복적으로 등장하는 것이 거슬렸었는데,
어떻게 해결하지 못 하고 있었어요 ㅎ ㅎ..

피드백 주신대로 배열을 만들면 아래처럼 훨씬 깔끔해지네요.

if (!repetitionString.match(RegularExpression.REGEX_VALID_NUMBER_FORMAT)) {
    const VALIDATOR_LIST = [
      validateNegativeNumber,
      validateDecimalNumber,
      validateZeroNumber,
      validateZeroStarting,
      validateNotNumber,
    ];
    VALIDATOR_LIST.forEach((fn) => fn(repetitionString));
    throw new Error(ErrorMessage.UNKNOWN_INVALID_NUMBER);
  }

크.. 👍 정말 감사합니다!!

INITIAL_DISTANCE: 0,
MOVE_LENGTH: 1,

VALID_TIMECOMPLEXITY: 1e7,

Choose a reason for hiding this comment

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

시간을 이렇게 신경쓴 것도 좋네요! TIMEOUT 기준이 천만정도 되는것 같은데, 천만정도로 잡은 이유가 있으실까요?!

Copy link
Author

Choose a reason for hiding this comment

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

Node.js의 V8 엔진의 연산 속도가 빠르기에 일반적으로 $O(10^7)$까지는 무리가 없고,
이를 넘을 경우에 Worker Threads를 사용해야 한다고 알고 있습니다.
이에 Node.js(20.17.0 버전) 특성을 고려하여 $10^7$으로 연산 횟수를 제한하였어요.

'자동차 경주' 프로그램의 어떠한 점 때문에 $10^7$까지만 가능하다고 말하기는 어려울 것 같습니다. 프로그램의 연산 과정이 단순하기에 이 이상의 연산도 처리가능할 것으로 보이기는 합니다! 😅

import RoundManager from './RoundManager.js';

class Game {
#CARS_LIST = [];

Choose a reason for hiding this comment

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

이 필드를 특별히 upper case로 작성하신 이유가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

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

제 실수입니다... 몇 번이고 이 변수를 봤었는데 왜 몰랐을까요 ..
필드가 어떤 상수를 나타내지도 않는데 upper case로 작성하였네요..

지적해주셔서 감사합니다!

#CARS_LIST = [];

constructor(names, repetitionNumber) {
this.nameList = CarAllocator.parseNames(names);

Choose a reason for hiding this comment

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

nameList를 Game class를 따로 들고 있어야 하나요?

Copy link
Author

Choose a reason for hiding this comment

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

리팩터링 중 빼먹었어요..

nameList는 배열 전달 후에 버려지는 변수라 const로 변경하는 것이 맞을 것 같네요.

어떻게 이렇게 개선 포인트를 잘 찾아주시는지.. 정말 감사합니다!🙇‍♂️🙇‍♂️🙇‍♂️

Copy link

@H-sooyeon H-sooyeon left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!
정말 열심히 하셨다는게 코드만 봐도 느껴졌어요. 👍

}

static print(contents) {
Console.print(contents);

Choose a reason for hiding this comment

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

print 메서드가 따로 있으니 코드 일관성을 위해 다른 메서드에서 사용하는 Console.print는 이 print로 변경하는건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

테스트에 있는 Console.print 말씀이시죠?

제가 놓쳤네요.. 잘 잡아주셔서 감사합니다! 👍


export default function validateNames(names) {
if (!names) throw new Error(ErrorMessage.EMPTY_NAMES_NOT_ALLOW);
if (!names.match(RegularExpression.REGEX_VALID_NAMES_FORMAT)) {

Choose a reason for hiding this comment

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

15.3

boolean 값이 아닌 string이나 number 값은 비교 연산자와 같은 방식으로 조건을 거시면 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

앗,, names.length == 0, names.match() !== ''이렇게 수정되어야 하겠네요..

감사합니다!!

Copy link

@j-nary j-nary left a comment

Choose a reason for hiding this comment

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

정규표현식을 잘 활용하신 것 같아요!
꼼꼼한 테스트 코드 작성도 잘 봤습니당 2주차 수고하셨어요 :)
시간 되시면 제 PR 코드리뷰 도 부탁드립니다!

@@ -0,0 +1,12 @@
export const InputView = {
Copy link

Choose a reason for hiding this comment

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

Object.freeze()로 동결시켜주는 건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

Object.freeze() 를 사용하면 내용을 외부에서 수정할 수 없게 되군요!

감사합니다. 3주 차 미션에는 반영하여 안정성을 높여 보겠습니다. ㅎㅎ👍

Comment on lines +4 to +5
export default class Input {
static async get() {
Copy link

Choose a reason for hiding this comment

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

class로 설계하신 이유가 있을까요?
class에 static 하나밖에 없으면 함수형 프로그래밍과의 차이점이 없다고 생각하는 편이어서요!
어떤 의도로 설계하셨는지 궁금합니다!

Copy link
Author

Choose a reason for hiding this comment

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

Input이라는 책임을 갖는 클래스를 만들어주고 싶었어요!
유지보수 측면에서 Input과 관련된 메서드는 모두 Input 클래스에 있으리라 예측하기 쉬우니까요.

get을 어떠한 함수형 유틸로 만들어 사용한다면, 기능은 동일하지만 Input 기능을 담당하는 곳이 한 곳이 아니라 여러 곳일 수도 있다는 가능성이 생기기에 클래스로 설계하였습니다.
Output도 마찬가지 이유로 class로 묶었습니다!

혹시 static 하나 밖에 없다면, 함수형으로 프로그래밍 하는 것이 정석인지(혹은 통상적으로 함수형으로 하는지) 여쭙습니다!

Copy link

Choose a reason for hiding this comment

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

static method만 있는 클래스를 유틸리티 클래스라고 합니다!
javascript에서는 유틸리티 함수들을 모듈로 분리하여 별도의 파일로 관리하는 것이 일반적입니다!
클래스 기반 설계에서 인스턴스를 사용해야하는 이유가 없다면, 유틸리티 클래스는 OOP 설계 철학과 상충될 수 있어요!

특히, static 메서드가 하나만 존재하는 (여러개를 그룹화시키기 위해 사용하는게 아닌) 경우 더더욱 클래스보다는 함수형으로 프로그래밍하는것이 좋다고 생각합니다 !!

Copy link
Author

Choose a reason for hiding this comment

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

클래스 기반 설계에서 인스턴스를 사용해야하는 이유가 없다면, 유틸리티 클래스는 OOP 설계 철학과 상충될 수 있어요!

이 부분을 모르고 잘못 작성했네요.. 🫠

굳이 인스턴스를 생성하지 않을 터인데 클래스로 만든다면,
OOP 설계 목적 내 클래스의 역할에 부합하지 못하는 것이군요..

피드백 감사합니다!! 🙇‍♂️

Comment on lines +4 to +5
export default function validateTimeComplexity(names, repetitionString) {
const N = names.split(',').length * Number(repetitionString);
Copy link

Choose a reason for hiding this comment

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

timeComplexity 로 네이밍 지으면 더 직관적으로 해석될 수 있을 것 같아요!
시간복잡도부분까지 생각하신 점 대단하네요! 배워갑니다 :)

Copy link
Author

Choose a reason for hiding this comment

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

알고리즘 문제를 풀다가 문득 시간 복잡도를 고려해야 하는 것이 아닌가 생각이 들었어요 ㅎㅎ.... 감사합니다 😆

혹시 timeComplexity로 네이밍 변경을 추천하시는 이유를 알 수 있을까요 이유를 스스로 찾아 보고 싶었으나 잘 모르겠습니다...

제가 validate라는 단어를 TimeComplexity앞에 넣은 이유는 해당 validator에서 검증 기능을 하는데, 혹여 validation에 실패하면 throw �Error 할 수 있다는 것을 동사를 붙여서 나타내고 싶었기 때문입니다!

Copy link

@BeA-Pro BeA-Pro left a comment

Choose a reason for hiding this comment

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

이전보다 성장하신게 느껴지네요👍👍👍
3주차도 화이팅입니다!

Comment on lines +21 to +28
let currentRepeat = 0;
while (currentRepeat !== this.repetitionNumber) {
this.roundManager.startRound(this.#CARS_LIST);
Output.printRoundResults(
this.roundManager.getCarsStatuses(this.#CARS_LIST),
);
currentRepeat += 1;
}
Copy link

Choose a reason for hiding this comment

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

해당 반복문은 for문을 사용하는 것이 더 적절해보이네요!

Copy link
Author

Choose a reason for hiding this comment

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

for 문을 사용하면 몇 회 반복하는지 직관적으로 보이기에 그런 걸까요?

며칠 지나고 코드를 다시 보니 해당 역할로서 while은 정말 별로긴하네요 ㅎㅎ...

감사합니다 👍

Copy link

Choose a reason for hiding this comment

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

for( let currentRepeat = 0; currentRepeat < this.repetitionNumber; currentRepeat += 1){
    this.roundManager.startRound(this.#CARS_LIST);
    Output.printRoundResults(
      this.roundManager.getCarsStatuses(this.#CARS_LIST),
    );
}

이런식으로 짜면 어떨까 생각해보았습니다!

Copy link
Author

Choose a reason for hiding this comment

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

몇 회를 반복할지 한 번에 보여서 훨씬 가독성 측면에서 좋은 것 같네요 😆

Comment on lines +6 to +8
if (N >= Rules.VALID_TIMECOMPLEXITY) {
throw new Error(ErrorMessage.OVER_VALID_TIMECOMPLEXITY);
}
Copy link

Choose a reason for hiding this comment

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

N이 큰 경우에 에러 처리도 하셨군요.. 꼼꼼하네요👍👍👍

Copy link
Author

Choose a reason for hiding this comment

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

알고리즘 문제를 풀다가 문득 미션에서도 Time Complexity를 고려해야 하는 게 아닌가 생각이 들었어요 ㅎ ㅎ
감사합니다! 😆

const mockRepetition = '5';

Console.readLineAsync
.mockResolvedValueOnce(mockNames)
Copy link

Choose a reason for hiding this comment

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

mockResolve라는 메서드도 있었군요. 배워갑니다~😄

Copy link
Author

Choose a reason for hiding this comment

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

비동기 함수를 mocking하여 return 변수를 지정할 때, mockResolved를 사용할 수 있더라구요!
입력 모듈에 상당히 요긴하게 썼어요 😋

Comment on lines +1 to +7
import { Random } from '@woowacourse/mission-utils';
import Car from './Car.js';
import { OutputView } from '../resources/Constants.js';
import Rules from '../resources/Rules.js';
import Output from '../utils/io/Output.js';
import CarAllocator from './CarAllocator.js';
import RoundManager from './RoundManager.js';
Copy link

Choose a reason for hiding this comment

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

사용하지 않는 모듈이 import 되어있는거 같은데요?

Copy link
Author

Choose a reason for hiding this comment

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

세상에.. 리팩터링 하다가 놓쳤네요 .. 🥲
꼼꼼히 봐주셔서 감사합니다!!

용현님도 3주 차 미션 파이팅입니다 🔥🔥🔥🔥

Copy link

@qowldk qowldk left a comment

Choose a reason for hiding this comment

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

리드미 파일을 상세하게 작성하신게 매우 인상깊습니다.
스스로 정한 규칙부터 구현에 집중한 부분까지 너무 꼼꼼하게 잘 작성된 파일을 본 것 같아요.

commit 양도 엄청 많은 거 보고 놀라고 갑니다..!
리드미 파일만 봐도 열정이 느껴지네요

과제 하시느라 수고 많으셨어요.
다음 주차 과제도 파이팅입니다!! 🔥🔥

Comment on lines +4 to +18
function validateNotNumber(repetitionString) {
if (repetitionString.match(RegularExpression.REGEX_NOT_NUMBER))
throw new Error(ErrorMessage.INPUT_CONTAIN_CHARACTER);
}

function validateZeroNumber(repetitionString) {
if (repetitionString.match(RegularExpression.REGEX_ONLY_ZERO))
throw new Error(ErrorMessage.ZERO_NUMBER_INPUT);
}

function validateZeroStarting(repetitionString) {
if (repetitionString.startsWith('0'))
throw new Error(ErrorMessage.STARTSWITH_ZERO_FORMAT);
}

Copy link

Choose a reason for hiding this comment

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

throw new Error 반복되는 부분도 하나의 함수로 작성해도 좋을 것 같아요.

function throwError(message) {
  throw new Error(ERROR_PREFIX + message);
}

이렇게 만든 throwError 함수를 호출해서 사용하는 것은 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

제안해주신 대로 함수화하는 것이 가독성 측면에서 훨씬 좋아보이네요!

4주 차 미션에 적용해봐야겠어요 ㅎㅎ👍

Comment on lines +19 to +27
function validateNegativeNumber(repetitionString) {
if (repetitionString.match(RegularExpression.REGEX_NEGATIVE_NUMBER))
throw new Error(ErrorMessage.NEGATIVE_NUMBER_INPUT);
}

function validateDecimalNumber(repetitionString) {
if (repetitionString.match(RegularExpression.REGEX_DECIMAL_NUMBER))
throw new Error(ErrorMessage.DECIMAL_NUMBER_INPUT);
}
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.

정규 표현식 넘 유용해요..😇
또한, 정규 표현식을 REGEX_NEGATIVE_NUMBER처럼 이름을 붙여주면, 굳이 정규식을 해석하지 않아도 되어 좋더라구요 !

감사합니다 😆

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.

6 participants