-
Notifications
You must be signed in to change notification settings - Fork 212
[자동차 경주] 주유나 미션 제출합니다. #190
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
base: main
Are you sure you want to change the base?
Changes from all commits
7ea4253
69a1e3e
4047caa
18550b8
a645d33
a21f2d7
56ebe20
7dbea56
cf53f63
7fe771f
d2498db
e2e58bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,62 @@ | ||
| # javascript-racingcar-precourse | ||
|
|
||
| # 🏎️ 자동차 경주 | ||
|
|
||
| ## 📋 구현 기능 목록 | ||
|
|
||
| --- | ||
|
|
||
| ### 1️⃣ 입출력 기본 프롬프트 | ||
|
|
||
| - [x] `Console.print("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)")` | ||
| - [x] `Console.readLineAsync("")`로 자동차 이름 입력 | ||
| - [x] `Console.print("시도할 횟수는 몇 회인가요?")` | ||
| - [x] `Console.readLineAsync("")`로 시도 횟수 입력 | ||
|
|
||
| --- | ||
|
|
||
| ### 2️⃣ 입력 파싱 & 검증 — 자동차 이름 | ||
|
|
||
| - [x] 쉼표 기준 분리, 각 이름 `trim()` | ||
| - [x] 빈 이름 금지, 전체 목록 빈 배열 금지 | ||
| - [x] 각 이름 길이 1~5자 제한 (초과 시 에러) | ||
| - [x] 오류 시 `[ERROR]`로 시작하는 메시지와 함께 `Error` throw | ||
|
|
||
| --- | ||
|
|
||
| ### 3️⃣ 입력 파싱 & 검증 — 시도 횟수 | ||
|
|
||
| - [x] 정수 문자열인지 확인 | ||
| - [x] 양의 정수(>0)만 허용 | ||
| - [x] 오류 시 `[ERROR]` 메시지와 함께 `Error` throw | ||
|
|
||
| --- | ||
|
|
||
| ### 4️⃣ 진행 규칙 구현 | ||
|
|
||
| - [x] 라운드마다 각 자동차에 대해 `Random.pickNumberInRange(0, 9)` | ||
| - [x] 4 이상이면 전진, 미만이면 정지 | ||
| - [x] 각 라운드 종료 후 `이름 : -...` 형식으로 상태 출력(진행도만큼 `-`) | ||
|
|
||
| --- | ||
|
|
||
| ### 5️⃣ 실행 결과 출력 형식 | ||
|
|
||
| - [x] 입력 후 `\n실행 결과` 출력 | ||
| - [x] 라운드 사이 빈 줄 출력(예시와 동일) | ||
| - [x] 모든 라운드 종료 후 우승자(복수 가능) 출력 | ||
|
|
||
| --- | ||
|
|
||
| ### 6️⃣ 예외 처리와 종료 흐름 | ||
|
|
||
| - [x] `run()`에서 모든 예외 `try/catch` | ||
| - [x] `[ERROR]`로 시작하는 메시지를 Console.print로 출력 | ||
| - [x] rethrow하여 테스트의 `rejects.toThrow`를 만족 | ||
| - [x] `process.exit()` 금지 | ||
|
|
||
| ### 7️⃣ 구조화/모듈화 & 스타일 | ||
|
|
||
| - [x] I/O(`App.js`) ↔ 비즈니스 로직(`RacingGame.js`) 분리 | ||
| - [x] 들여쓰기(depth) 2 이내, 3항 연산자 사용 금지 | ||
| - [x] 함수는 한 가지 일만 하도록 분리 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,4 +57,59 @@ describe("자동차 경주", () => { | |
| // then | ||
| await expect(app.run()).rejects.toThrow("[ERROR]"); | ||
| }); | ||
|
|
||
| // 파라미터화 테스트 추가 | ||
| describe.each([ | ||
| ["", "[ERROR] 자동차 이름이 비어 있습니다."], | ||
| ["pobi,javaji", "[ERROR] 자동차 이름은 5자 이하여야 합니다."], | ||
| ["pobi, ", "[ERROR] 빈 이름은 허용되지 않습니다."], | ||
| [" ,woni", "[ERROR] 빈 이름은 허용되지 않습니다."], | ||
| ])("이름 검증 - 입력: %s", (nameLine, errorMsg) => { | ||
| test("run()는 [ERROR]로 reject 되어야 한다", async () => { | ||
| mockQuestions([nameLine]); | ||
| const app = new App(); | ||
| await expect(app.run()).rejects.toThrow(errorMsg); | ||
| }); | ||
| }); | ||
|
|
||
| describe.each([ | ||
| ["pobi,woni", "0", "[ERROR] 시도 횟수는 1 이상이어야 합니다."], | ||
| ["pobi,woni", "-1", "[ERROR] 시도 횟수는 1 이상이어야 합니다."], | ||
| ["pobi,woni", "abc", "[ERROR] 시도 횟수는 숫자여야 합니다."], | ||
| ["pobi,woni", " ", "[ERROR] 시도 횟수는 숫자여야 합니다."], | ||
| ])("시도 횟수 검증 - 입력: %s / %s", (nameLine, attemptLine, errorMsg) => { | ||
| test("run()는 [ERROR]로 reject 되어야 한다", async () => { | ||
| mockQuestions([nameLine, attemptLine]); | ||
| const app = new App(); | ||
| await expect(app.run()).rejects.toThrow(errorMsg); | ||
| }); | ||
| }); | ||
|
|
||
| describe.each([ | ||
| [ | ||
| [4, 3], | ||
| ["pobi : -", "woni : ", "최종 우승자 : pobi"], | ||
| ], | ||
| [ | ||
| [3, 4], | ||
| ["pobi : ", "woni : -", "최종 우승자 : woni"], | ||
| ], | ||
| [ | ||
| [4, 4], | ||
| ["pobi : -", "woni : -", "최종 우승자 : pobi, woni"], | ||
| ], | ||
| ])("한 라운드 시뮬레이션 - 랜덤: %j", (randoms, expectedLogs) => { | ||
| test("보드/우승자 출력이 형식에 맞아야 합니다.", async () => { | ||
| const logSpy = getLogSpy(); | ||
| mockQuestions(["pobi,woni", "1"]); | ||
| mockRandoms(randoms); | ||
|
|
||
| const app = new App(); | ||
| await app.run(); | ||
|
|
||
| expectedLogs.forEach((log) => { | ||
| expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log)); | ||
| }); | ||
| }); | ||
| }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. describe.each를 통해서 한번에 테스트를 묶으니까 코드가 더 간결하네요
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반복되는 케이스가 많아서 |
||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,46 @@ | ||
| import { Console } from "@woowacourse/mission-utils"; | ||
| import { RacingGame } from "./RacingGame.js"; | ||
| import { ERROR, PROMPT } from "./constants/messages.js"; | ||
|
|
||
| class App { | ||
| async run() {} | ||
| async run() { | ||
| Console.print(PROMPT.ASK_NAMES); | ||
| try { | ||
| const nameLine = await Console.readLineAsync(""); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. readLienAsync에 PROMPT.ASK_NAMES을 작성하면 콘솔에 출력되고 입력을 받을 수 있습니다!! 따로 Print 안해도 될것 같아서 좋을것 같네요!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 출력 형식을 명시적으로 구분하고 싶어서 Console.print로 분리했는데, |
||
| Console.print(PROMPT.ASK_ATTEMPTS); | ||
| const attemptLine = await Console.readLineAsync(""); | ||
|
|
||
| const game = new RacingGame(nameLine, attemptLine); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| const result = game.playAllRounds(); | ||
|
|
||
| this.#printExecutionHeader(); | ||
| this.#printBoards(result.boards); | ||
| this.#printWinners(result.winners); | ||
| } catch (error) { | ||
| const message = error?.message ?? ERROR.UNKNOWN; | ||
| Console.print(message); | ||
| throw error; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에서 error message 처리해서 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. error를 발생시키고 종료해야해서 throw error 가 필요하지 않나요 ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
테스크 환경에서
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 앗 제가 생각이 여기서 꼬였었나봐요... 왜 메세지를 단순히 error.message로 안하셨을까? 하고 뜯어보다가 message 출력하고 다시 throw?하면서 삭제해도 될 것 같다고 생각했어요.... throw하는게 맞습니다ㅠㅠ |
||
| } | ||
| } | ||
|
|
||
| #printExecutionHeader() { | ||
| Console.print(""); | ||
| Console.print(PROMPT.EXEC_HEADER); | ||
| } | ||
|
|
||
| #printBoards(boards) { | ||
| for (const board of boards) { | ||
| for (const line of board) { | ||
| Console.print(line); | ||
| } | ||
| Console.print(""); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Console.print("")가 반복되는데 음.. print함수를 따로 만들어서 증복을 줄이는 방법은 어떨까요 ? 그러면 출력 요소가 전부 분리되어있는데 이또한 줄어들 수 있을것 같네요!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. print 함수를 헬퍼로 추출해서 중복을 줄이는 방향이 깔끔하겠네요! |
||
| } | ||
| } | ||
|
|
||
| #printWinners(winners) { | ||
| const line = `최종 우승자 : ${winners.join(", ")}`; | ||
| Console.print(line); | ||
| } | ||
| } | ||
|
|
||
| export default App; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| import { Random } from "@woowacourse/mission-utils"; | ||
| import { ERROR } from "./constants/messages"; | ||
|
|
||
| const MOVE_THRESHOLD = 4; | ||
| const RANDOM_MIN = 0; | ||
| const RANDOM_MAX = 9; | ||
|
Comment on lines
+4
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이미 충분히 좋지만 MOVE_THRESHOLD = 4 상수의 의미가 ‘전진 조건 최소값’ 임을 이름으로 드러내면 좀 더 확실하게 알 수 있을 것 같아요! FORWARD_THRESHOLD 또는 MOVE_CONDITION_MIN_VALUE 이런식으로요! |
||
|
|
||
| export class RacingGame { | ||
| #cars; | ||
| #attempts; | ||
|
|
||
| constructor(nameLine, attemptLine) { | ||
| const names = this.#parseNames(nameLine); | ||
| const attempts = this.#parseAttempts(attemptLine); | ||
| this.#cars = names.map((name) => ({ name, position: 0 })); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 cars의 각 car는 |
||
| this.#attempts = attempts; | ||
| } | ||
|
|
||
| playAllRounds() { | ||
| const boards = []; | ||
| for (let round = 0; round < this.#attempts; round += 1) { | ||
| this.#playOneRound(); | ||
| boards.push(this.#formatBoard()); | ||
| } | ||
| const winners = this.#determineWinners(); | ||
| return { boards, winners }; | ||
| } | ||
|
Comment on lines
+19
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 매 라운드 자동차가 이동한 거리를 배열에 저장하고 모든 라운드가 다 끝났을때 한 번에 출력하는 방식입니다. index 9c34162..2921c0b 100644
--- a/src/App.js
+++ b/src/App.js
@@ -11,11 +11,10 @@ class App {
const attemptLine = await Console.readLineAsync("");
const game = new RacingGame(nameLine, attemptLine);
- const result = game.playAllRounds();
+ const winners = game.playAllRounds();
this.#printExecutionHeader();
- this.#printBoards(result.boards);
- this.#printWinners(result.winners);
+ this.#printWinners(winners);
} catch (error) {
const message = error?.message ?? ERROR.UNKNOWN;
Console.print(message);
@@ -28,15 +27,6 @@ class App {
Console.print(PROMPT.EXEC_HEADER);
}
- #printBoards(boards) {
- for (const board of boards) {
- for (const line of board) {
- Console.print(line);
- }
- Console.print("");
- }
- }
-
#printWinners(winners) {
const line = `최종 우승자 : ${winners.join(", ")}`;
Console.print(line);
diff --git a/src/RacingGame.js b/src/RacingGame.js
index d6ccf70..5c32b74 100644
--- a/src/RacingGame.js
+++ b/src/RacingGame.js
@@ -1,5 +1,5 @@
-import { Random } from "@woowacourse/mission-utils";
-import { ERROR } from "./constants/messages";
+import { Random, Console } from "@woowacourse/mission-utils";
+import { ERROR } from "./constants/messages.js";
const MOVE_THRESHOLD = 4;
const RANDOM_MIN = 0;
@@ -17,13 +17,11 @@ export class RacingGame {
}
playAllRounds() {
- const boards = [];
for (let round = 0; round < this.#attempts; round += 1) {
this.#playOneRound();
- boards.push(this.#formatBoard());
}
const winners = this.#determineWinners();
- return { boards, winners };
+ return winners
}
#playOneRound() {
@@ -32,16 +30,9 @@ export class RacingGame {
if (randomValue >= MOVE_THRESHOLD) {
car.position += 1;
}
+ Console.print(`${car.name} : ${'-'.repeat(car.position)}`);
}
- }
-
- #formatBoard() {
- const lines = [];
- for (const car of this.#cars) {
- const hyphens = "-".repeat(car.position);
- lines.push(`${car.name} : ${hyphens}`);
- }
- return lines;
+ Console.print('');
}
#determineWinners() { |
||
|
|
||
| #playOneRound() { | ||
| for (const car of this.#cars) { | ||
| const randomValue = Random.pickNumberInRange(RANDOM_MIN, RANDOM_MAX); | ||
| if (randomValue >= MOVE_THRESHOLD) { | ||
| car.position += 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #formatBoard() { | ||
| const lines = []; | ||
| for (const car of this.#cars) { | ||
| const hyphens = "-".repeat(car.position); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 변수명이 직관적이고 명확하다는 장점이 있습니다만, 변수명이 hyphens는 살짝 specific 하지않나? 라고 생각했습니다. positionIndicator같은 변수 명이면 위치를 나타내는 표시 라는 목적이 있어서, 나중에 출력 형식이 *나 >로 바뀌어도 변수명을 바꾸지 않아도 되는 장점이 있기에 의견 남깁니다! |
||
| lines.push(`${car.name} : ${hyphens}`); | ||
| } | ||
| return lines; | ||
| } | ||
|
|
||
| #determineWinners() { | ||
| const max = this.#cars.reduce((maxDistance, car) => { | ||
| if (car.position > maxDistance) return car.position; | ||
| return maxDistance; | ||
| }, 0); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분은 간단하게
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 우와 |
||
| const names = []; | ||
| for (const car of this.#cars) { | ||
| if (car.position === max) { | ||
| names.push(car.name); | ||
| } | ||
| } | ||
| return names; | ||
|
Comment on lines
+52
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 코드도 동작에는 문제가 없지만 filter, map 을 사용하면 코드가 더 깔끔할거 같습니다. #determineWinners() {
const max = this.#cars.reduce((maxDistance, car) => {
if (car.position > maxDistance) return car.position;
return maxDistance;
}, 0);
const winners = this.#cars.filter((car) => car.position === max);
const winnerNames = winners.map((car) => car.name);
return winnerNames;
} |
||
| } | ||
|
|
||
| #parseNames(nameLine) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 index d6ccf70..3c7f32b 100644
--- a/src/RacingGame.js
+++ b/src/RacingGame.js
@@ -1,5 +1,5 @@
import { Random } from "@woowacourse/mission-utils";
-import { ERROR } from "./constants/messages";
+import { ERROR } from "./constants/messages.js";
const MOVE_THRESHOLD = 4;
const RANDOM_MIN = 0;
@@ -10,7 +10,8 @@ export class RacingGame {
#attempts;
constructor(nameLine, attemptLine) {
- const names = this.#parseNames(nameLine);
+ const carNames = this.#parseCarNames(nameLine);
+ this.#validateCarNames(carNames);
const attempts = this.#parseAttempts(attemptLine);
this.#cars = names.map((name) => ({ name, position: 0 }));
this.#attempts = attempts;
@@ -58,24 +59,20 @@ export class RacingGame {
return names;
}
- #parseNames(nameLine) {
- const raw = (nameLine ?? "").trim();
- if (raw === "") {
- throw new Error(ERROR.EMPTY_NAMES);
- }
-
- const nameTokens = raw.split(",").map((s) => s.trim());
-
- for (const nameToken of nameTokens) {
- if (nameToken === "") {
+ #validateCarNames(carNames) {
+ for (const name of carNames) {
+ if (name === '') {
throw new Error(ERROR.EMPTY_NAME_TOKEN);
}
if (nameToken.length > 5) {
throw new Error(ERROR.NAME_TOO_LONG);
}
}
+ }
- return nameTokens;
+ #parseCarNames(nameLine) {
+ const carNames = nameLine.split(",").map((el) => el.trim());
+ return carNames;
}
#parseAttempts(attemptLine) {최종적으로는 이 부분이 |
||
| const raw = (nameLine ?? "").trim(); | ||
| if (raw === "") { | ||
| throw new Error(ERROR.EMPTY_NAMES); | ||
| } | ||
|
|
||
| const nameTokens = raw.split(",").map((s) => s.trim()); | ||
|
|
||
| for (const nameToken of nameTokens) { | ||
| if (nameToken === "") { | ||
| throw new Error(ERROR.EMPTY_NAME_TOKEN); | ||
| } | ||
| if (nameToken.length > 5) { | ||
| throw new Error(ERROR.NAME_TOO_LONG); | ||
| } | ||
| } | ||
|
Comment on lines
+69
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반복문에서 여러 조건을 한 번에 검증하고 있는데 js 내장 매서드를 사용해서 한 번에 한 조건으로 검증하면 들여쓰기를 줄일 수 있을 것 같아요.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제안해주신 방향으로 리팩토링하면 훨씬 깔끔한 코드가 될 것 같아요! 감사합니다 👍🏻 |
||
|
|
||
| return nameTokens; | ||
| } | ||
|
|
||
| #parseAttempts(attemptLine) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 함수명이 전반적으로 일관적이어서 이해가 좋습니다!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 저도 비슷한 느낌을 받았는데, 지금은 파싱 로직과 유효성 검사 로직이 함께 포함되어 있다보니 두 관심사를 나눠서 각각 메서드로 사용하는 것도 또 다른 방법이 될 것 같습니다! |
||
| const raw = (attemptLine ?? "").trim(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ?? "" 사용도 좋네요 !
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 감사합니다! 😊 |
||
|
|
||
| if (!/^-?\d+$/.test(raw)) { | ||
| throw new Error(ERROR.ATTEMPTS_NAN); | ||
| } | ||
|
|
||
| const randomValue = Number(raw); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 어차피 Number 처리를 했다면 위에서 정규표현식을 굳이 사용하지 않고
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이번에는 음수 입력 케이스 잡아내고 싶어서 정규식으로 확인했습니다! |
||
|
|
||
| if (!Number.isSafeInteger(randomValue) || randomValue <= 0) { | ||
| throw new Error(ERROR.ATTEMPTS_POSITIVE); | ||
| } | ||
| return randomValue; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| export const PROMPT = { | ||
| ASK_NAMES: "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)", | ||
| ASK_ATTEMPTS: "시도할 횟수는 몇 회인가요?", | ||
| EXEC_HEADER: "실행 결과", | ||
| }; | ||
| export const ERROR = { | ||
| EMPTY_NAMES: "[ERROR] 자동차 이름이 비어 있습니다.", | ||
| EMPTY_NAME_TOKEN: "[ERROR] 빈 이름은 허용되지 않습니다.", | ||
| NAME_TOO_LONG: "[ERROR] 자동차 이름은 5자 이하여야 합니다.", | ||
| ATTEMPTS_NAN: "[ERROR] 시도 횟수는 숫자여야 합니다.", | ||
| ATTEMPTS_POSITIVE: "[ERROR] 시도 횟수는 1 이상이어야 합니다.", | ||
| UNKNOWN: "[ERROR] 알 수 없는 오류가 발생했습니다.", | ||
| }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상수 분리 너무 깔끔하네요 최고!!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상수 분리에 대한 리뷰가 있었어서 적용해봤습니다 😁
Comment on lines
+6
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 맞습니다 윗분님들 말씀대로 상수 분리 깔끔하게 잘 하셔서 인상적입니다! 추가로Object.freeze()를 적용하면 불변성을 보장할 수 있어 좋은 방법이 있어 남기고 갑니다 ㅎㅎ |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| declare module "@woowacourse/mission-utils" { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ts 파일이 있는데 생성한 이유가 있을까요?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| export const Console: { | ||
| readLineAsync(prompt?: string): Promise<string>; | ||
| print(message: string): void; | ||
| }; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 타입 선언 너무 좋습니다!!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
예외 케이스와 단일 라운드 시뮬레이션은 훌륭하게 커버되어있는 것 같아요!
그래도 제 생각이긴 하지만 attempts > 1일 때 누적 이동 결과를 검증하는 테스트가 추가되면 테스트케이스 완성도가 좀 더 올라가지 않을까 생각해봅니다...!