-
Notifications
You must be signed in to change notification settings - Fork 208
[자동차 경주] 이환섭 미션 제출합니다. #186
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?
Conversation
- constants.js: 게임 설정 상수 정의 - ErrorMessage.js: 에러 메시지 중앙 관리
- Car 클래스: 이름과 위치 정보 관리 - move(): 0-9 랜덤값으로 전진 판단 - shouldAdvance(): 전진 여부 결정 로직
- Validator 클래스: 입력 검증 담당 - validateCarNames(): 자동차 이름 검증 (길이, 공백 체크) - validateMovementCount(): 시도 횟수 검증 (숫자, 범위 체크)
- GameView: 모든 메서드를 static으로 구현하여 상태 없는 디자인 - 사용자 입력 처리 및 게임 결과 출력 - printCarStatus(), printRoundResult(), printWinners() 구현
- GameController: 전체 게임 흐름 관리 및 조율 - run(): 게임 실행 전체 프로세스 통합 - 입력 처리, 게임 진행, 우승자 판정 기능
- Controller에 전체 로직 위임하여 App은 진입점 역할만 수행 - Clean Code 원칙에 따라 단순하고 명확한 구조로 개선
- 프로젝트 구조 및 아키텍처 설명 - MVC 패턴 기반 설계 원칙 문서화 - 기능 요구사항 및 구현 내용 정리
- POSIX 규칙 준수 위해 EOF 개행 추가
- 게임 실행 흐름을 보여주는 시퀀스 다이어그램 추가 - 계층 구조를 보여주는 아키텍처 다이어그램 추가 - GitHub 표시를 위한 PNG 이미지 생성
- 자동차 이름 관련 에러 메시지 4가지로 세분화 - 이동 횟수 관련 에러 메시지 6가지로 세분화 - 구체적인 에러 원인 파악 가능하도록 개선 - 사용자에게 명확한 피드백 제공
- 세분화된 에러 메시지 적용 - 변수명을 더 직관적이고 이해하기 쉽게 변경 - JSDoc 주석 추가로 코드 가독성 향상 - 사용하지 않는 메서드 제거
- 기능 테스트 케이스 상세화 (단일/다중 라운드, 다중 우승자) - 예외 테스트 케이스 확장 (자동차 이름, 이동 횟수) - Given-When-Then 패턴으로 주석 구조화 - 한글 주석으로 테스트 의도 명확화
- 시스템 아키텍처 다이어그램 이미지로 교체 - 코드 메트릭 업데이트 (297줄, 16개 테스트 통과) - 에러 메시지 세분화 내용 추가 - 검증 로직 개선 및 변수명 직관화 내용 추가 - 테스트 결과 상세화 (기능/예외 테스트, BDD 패턴 적용)
- 사용하지 않는 상수 제거 - 코드 정리 및 최적화
- Car 모델에 고유 ID 시스템 추가 (idCounter) - 중복 이름이 있을 때 ID로 구분하여 표시 (예: pobi#1, pobi#2) - GameView에서 중복 이름 구분 출력 구현 - 중복 이름 처리 테스트 추가 - 모든 기존 테스트 통과 확인
manNomi
left a comment
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.
MVC 패턴을 깔끔하게 쓰셔서 코드를 읽는데 시간이 많이 단축되었습니다
제코드는 항상 잘못 작성된 패턴이라 제가 읽기에도 벅찼는데 작성자분 코드는
패턴 덕분에 읽기 좋았습니다 좋은코드 감사합니다!
| async run() { | ||
| const controller = new GameController(); | ||
| await controller.run(); | ||
| } |
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.
저 또한 고민했던 것인데
저는 App.js 자체가 작은 컨트롤러라고 생각했었습니다
MVC를 적용할때 콘트롤러가 대부분의 요구사항에는 하나 뿐이고요
App.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.
저도 그 부분이 헷갈려서 처음에는 App.js에 모든 컨트롤러의 내용의 코드를 넣었다가,
지난 피드백에 App.js가 무거운 느낌이라는 피드백을 받아, 따로 컨트롤러를 생성해 전체 게임 흐름을 시작하는 오케스트레이션 역할을 진행 했습니다!
지금처럼의 작은 프로그램 같은 경우는 상관없지만, 나중에 확장성이랑 유지보수 측면을 생각하면 App.js를 조금 가볍게 진행했습니다!
| // 자동차 이름 입력 및 검증 | ||
| const carNamesInput = await this.getCarNamesInput(); | ||
| const carNames = this.parseCarNames(carNamesInput); | ||
| Validator.validateCarNames(carNames); |
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.
Static 선언 validator 좋은데요!!
혹시 validatror를 static 선언하는것과 객체로 선언하는것의 차이가 있다고 생각하시나요?
또는 함수로 선언할때도요
모두 필드를 사용하거나 하는 함수가 아니라서 클래스로 분리하는 이유가 있을까 고민이 되더라고요
그리고 class로 분리했을때 Validator.validate 가 겹치는 느낌이라
Validator.carNames와같이 접근가능하도록 하는것은 어떨까요 ? 의미상 빠르게 읽히더라고요
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.
그리고 저도 고민했던 내용인데
Validator에 모든 validate를 묶는것이 옳을까였습니다.
자동차 이름의 제한은 Car 객체의 책임이지 않나 싶기도 하더라고요
작성자분 처럼 저도 하나에 모아두었었는데 고민이 되었던것 같습니다
작성자분은 어떤 이유로 하나로 묶으신건가요 ??
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.
Static 선언의 차이
->static으로 선언한것은 객체의 입력에만 의존하고 내부 상태를 보관하지 않고, 인스턴스 필드가 없으므로 객체 생성이 불필요하다는 판단하에 진행하였고, 사용 단순화를 통해서 진행했습니다!
class로 분리했을때 Validator.validate 가 겹치는 느낌이라
Validator.carNames와같이 접근가능하도록 하는것은 어떨까요 ?
->이부분은 생각해본적 없는데 이런 방법도 있었군요! 감사합니다! :)
Validator에 모든 validate를 묶는것이 옳을까?
-> 이 부분은 확장성과 유지보수성, 책임성을 염두에 두었습니다! car.js는 비지니스 로직에 염두하여 책임성을 controller, model 사이에 진행하고, 후에 검증단계에서 추가할 부분이 생기면 그부분을 단순히 추가하는 부분에 대해서 car.js에 넣으면 유지보수가 어렵다고 생각합니다!
| /** | ||
| * 게임 컨트롤러 (MVC - Controller) | ||
| * 전체 게임 흐름을 관리하고 조율하는 역할 | ||
| */ |
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.
콘트롤러가 로직이 다소 많은것 같다는 생각도 듭니다
무슨일을 해라 명령을 해주는것이 콘트롤러의 역할이라고 생각이 드는데
로직 또한 포함이 되어있어서 명령을 내리는 사람이 모든 일을 하는 느낌이라
저또한 고민이되네요.. model에게 일을 시키기 위해서는 일을 알아야하니까요
그래서 서비스 계층이 있는것 같기도 하고요 지금 코드가 의도도 이해되고 구조도 적합해서 수정할필요 없이 좋다고 생각이 들기도 합니다!
| return this.name; | ||
| } | ||
| } | ||
|
|
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.
jsDoc 깔끔하게 잘쓰셨네요..
저도 적용한다고 하고 못했는데 너무 좋은것 같스빈다
| this.name = name; | ||
| this.position = 0; | ||
| this.id = ++Car.idCounter; // 고유 ID 할당 | ||
| } |
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.
오!!
저는 증복된 이름의 경우 애러처리했는데
이런 방법도 존재하는군요
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.
저도 이부분 나중에 하나씩 예외 사항 확인 테스트 하다가 같은 이름은 어떤식으로 표기해야되지??
index를 통해서 표기하자는 생각이 들어 진행했습니다!
name(a),name(b) 이런식으로 표기 하려다가 이것보다는 index를 통해서 간단한게 좋을꺼 같아서 진행했습니다!
inseong01
left a comment
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주 차 미션하시느라 수고하셨습니다~
| * 전체 게임 실행 흐름 관리 | ||
| */ | ||
| async run() { | ||
| // 자동차 이름 입력 및 검증 |
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.
run 메서드 코드가 명확해서 내부 주석은 제외해도 좋을 것 같습니다.
| for (const car of cars) { | ||
| if (car.position > maxPosition) { | ||
| maxPosition = car.position; | ||
| } | ||
| } |
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.
| for (const car of cars) { | |
| if (car.position > maxPosition) { | |
| maxPosition = car.position; | |
| } | |
| } | |
| const carPositions = cars.map((car) => car.position); | |
| const maxPosition = Math.max(...carPositions); |
이렇게 하면 들여쓰기 깊이를 줄일 수 있을 것 같아요.
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.
감사합니다 ! :)
자동차 경주 게임
프로젝트 개요
SOLID 원칙과 MVC 패턴을 적용한 객체지향 자동차 경주 게임을 구현했습니다. 단일 책임 원칙을 준수하여 코드의 유지보수성과 확장성을 높이고, 깔끔한 아키텍처를 구축했습니다.
주요 성과
완료된 기능
코드 메트릭
시스템 아키텍처
파일 구조
src/
├── constants/ # 상수 및 에러 메시지 중앙 관리
├── models/ # 도메인 모델 (Car)
├── validators/ # 검증 로직 분리
├── views/ # UI 출력 담당
├── controllers/ # 게임 흐름 제어
├── App.js # 메인 앱 (Facade 패턴)
└── index.js # 진입점
아키텍처 다이어그램
주요 리팩토링 이력
코드 분리 및 모듈화
문제점: 모든 로직이 App.js에 집중되어 단일 책임 원칙 위배
해결: 8개 파일로 분리하여 각 모듈의 책임 명확화
에러 메시지 세분화 및 중앙 관리
문제점: 에러 메시지 하드코딩, 일반적인 메시지로 구체적 문제 파악 어려움
해결: ErrorMessage.js로 중앙 관리, 구체적인 에러 메시지 제공
MissionUtils API 오류 수정
문제: readLineAsync() 인자 중복 전달로 인한 에러
해결: 입력 처리 로직 개선
랜덤값 범위 오류 수정
문제: 요구사항(0
9 중 4 이상)과 다른 구현(49만 선택)해결: 올바른 랜덤값 범위 적용
검증 로직 통합 및 변수명 개선
문제: 검증 로직 산재, 애매한 변수명
해결: Validator 클래스로 통합, 명확한 변수명 적용
테스트 결과
기능 테스트 (4개)
예외 처리 테스트 (12개)
적용된 디자인 패턴
도전과 성과
성공한 부분
학습한 점
코드 품질 개선