본 포스팅은 우아한테크코스 2주차가 종료된 11월 2일 오전 12시에 공개로 전환되었습니다!
1주차 코드리뷰 종합해보기
✔️ 제시된 요구사항 목록
🚀 기능 요구 사항
- 초간단 자동차 경주 게임을 구현한다.
- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
- 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
- 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
- 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
- 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.
🎯 프로그래밍 요구 사항
- JDK 17 버전에서 실행 가능해야 한다. JDK 17에서 정상적으로 동작하지 않을 경우 0점 처리한다.
- 프로그램 실행의 시작점은 Application의 main()이다.
- build.gradle 파일을 변경할 수 없고, 외부 라이브러리를 사용하지 않는다.
- Java 코드 컨벤션 가이드를 준수하며 프로그래밍한다.
- 프로그램 종료 시 System.exit()를 호출하지 않는다.
- 프로그램 구현이 완료되면 ApplicationTest의 모든 테스트가 성공해야 한다. 테스트가 실패할 경우 0점 처리한다.
- 프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 이름을 수정하거나 이동하지 않는다.
추가된 요구 사항
- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
- 힌트 : indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
- 3항 연산자를 쓰지 않는다.
- 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.
- JUnit 5와 AssertJ를 이용하여 본인이 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인한다.
- 테스트 도구 사용법이 익숙하지 않다면 test/java/study를 참고하여 학습한 후 테스트를 구현한다.
라이브러리
- JDK에서 제공하는 Random 및 Scanner API 대신 camp.nextstep.edu.missionutils에서 제공하는 Randoms 및 Console API를 사용하여 구현해야 한다.
- Random 값 추출은 camp.nextstep.edu.missionutils.Randoms의 pickNumberInRange()를 활용한다.
- 사용자가 입력하는 값은 camp.nextstep.edu.missionutils.Console의 readLine()을 활용한다.
사용 예시
- 0에서 9까지의 정수 중 한 개의 정수 반환
Randoms.pickNumberInRange(0,9);
✏️ 과제 진행 요구 사항
- 미션은 java-racingcar-6 저장소를 Fork & Clone해 시작한다.
- 기능을 구현하기 전 docs/README.md에 구현할 기능 목록을 정리해 추가한다.
- Git의 커밋 단위는 앞 단계에서 docs/README.md에 정리한 기능 목록 단위로 추가한다.
- 커밋 메시지 컨벤션 가이드를 참고해 커밋 메시지를 작성한다.
- 과제 진행 및 제출 방법은 프리코스 과제 제출 문서를 참고한다.
✔️ 게임 프로세스 요약 📝
1. 사용자로부터 자동차 이름을 입력받는 기능
🚫 예외 1-1) 이름의 길이가 1자 미만, 5자 초과 경우
🚫 예외 1-2) 자동차의 수가 1대 미만인 경우
2. 사용자로부터 각 자동차의 이동 횟수를 입력받는 기능
🚫 예외 1-1) 숫자 이외의 값이 포함되어 있는 경우
3. 0에서 9 사이의 무작위 값을 생성하는 기능
4. 게임 우승자를 반환하는 기능
- 4-1. 가장 많이 앞선 자동차를 판별
- 4-2. 우승자는 1명 이상일 수 있음
5. 게임 진행 기능
- 5-1. 입력 메시지 출력하기
- 5-2. 우승자 출력하기
6. 게임 반복 기능
- 6-1. 현재 경주 상황(자동차 이름, 자동차 현재 위치) 출력하기
✔️ 기능 목록 🚀
1. 사용자로부터 자동차 이름을 입력받는 기능
- 예외 1-1) 이름의 길이가 5자를 초과하는 경우
- 예외 1-2) 이름에 중복이 존재하는 경우
- 예외 1-3) 자동차의 수가 2대 미만인 경우
2. 사용자로부터 각 자동차의 이동 횟수를 입력받는 기능
- 예외 1-1) 숫자 이외의 값이 포함되어 있는 경우
3. 0에서 9 사이의 무작위 값을 생성하는 기능
4. 게임 우승자를 반환하는 기능
- 가장 많이 앞선 자동차를 판별
- 우승자는 1명 이상일 수 있음
5. 게임 진행 기능
- 입력 메시지 출력하기
- 우승자 출력하기
6. 게임 반복 기능
- 현재 경주 상황(자동차 이름, 경주 상황) 출력하기
✔️ 클래스 설계 📚
- verification
- InputVerification : 주어진 입력이 올바른지 검증하는 객체
- checkAll() : 전체 검증을 실시하는 함수
- checkNameLength() : 입력값의 길이가 5자 이하인지 검증하는 함수
- checkNameDuplicate() : 입력값 중 중복된 값이 있는지 검증하는 함수
- checkCarCount() : 입력한 자동차의 수가 2대 이상인지 검증하는 함수
- checkInputType() 입력값이 숫자로만 이루어져 있는지 검증하는 함수
- InputVerification : 주어진 입력이 올바른지 검증하는 객체
- view
- InputView : 사용자로부터 입력을 받는 객체
- carNames() : 자동차의 이름을 입력받는 함수
- moveCount() : 이동 횟수를 입력받는 함수
- OutputView : 메시지를 출력하는 객체
- printInputNameMessage() : 자동차 이름 입력 메시지를 출력하는 함수
- printInputCountMessage() : 시도 횟수 입력 메시지를 출력하는 함수
- printCarName() : 자동차의 이름을 출력하는 함수
- printRaceStatus() : 자동차의 현재 경주 상황을 출력하는 함수
- printWinner() : 우승자를 출력하는 함수
- InputView : 사용자로부터 입력을 받는 객체
- domain
- Car : 자동차 객체
- move() : 자동차가 전진하는 함수
- CarDTO : Car의 현재 데이터를 저장하는 객체
- getName() : 자동차의 이름을 저장하는 함수
- getRaceStatus() : 자동차의 현재 경주 상황을 저장하는 함수
- Car : 자동차 객체
- service
- RaceService : 게임 진행을 돕는 객체
- createRandomNumber() : 0에서 9 사이의 랜덤 값을 생성하는 함수
- isMoreThanFour() : 랜덤 값이 4 이상인지 판별하는 함수
- GameManageService : 게임을 진행하는 객체
- getFinalResult() : 함수
- getBestCar() : 함수
- RaceService : 게임 진행을 돕는 객체
- controller
- GameManageController : 전반적인 게임을 진행하는 객체
- start() : 게임을 시작하는 함수
- gameProgress() : 게임을 진행하는 함수
- finish() : 게임을 종료하는 함수
- GameManageController : 전반적인 게임을 진행하는 객체
✔️ 구현 🛠️
https://jihyun-devstory.tistory.com/11
1주차 때 가장 아쉬웠던 점은 도메인을 따로 분리하지 못했다는 것이다. MVC 패턴을 적용하면서 도메인 분리 시 데이터를 어떻게 다른 계층으로 전달해야할지 많은 고민이 있었기 때문이다. 따라서 이번 2주차 때 반드시 도메인을 분리해보는 것이 목표였다. 하지만 도메인을 단순히 분리하는 것보다 '왜 분리해야 하는지, 어떻게 데이터를 전달해야 하는지' 등에 대한 명확한 고찰이 필요하다는 생각이 들었다.
1주차 때 야구 게임을 구현해보았기에 Service, View, Controller 계층을 분리하는 과정은 크게 어렵지 않았다. 도메인은 결론적으로 Car 객체와 CarDTO를 만들어 구현하였다. 자세한 내용은 이후 어려웠던 점에서 다룰 것이다. 또한, 지난 주차에는 배열을 사용했는데 이번 주차에서는 컬렉션을 사용하였다. 배열보다 사용할 수 있는 API가 많아 훨씬 편리하다는 것을 깨달았다. 마지막으로 리팩토링 과정에서 출력 메시지나 숫자의 범위와 같은 값은 상수 객체로 분리하였다.
아래 블로그들을 통해 DTO에 대한 감을 조금씩 잡았다.
https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/
https://tecoble.techcourse.co.kr/post/2021-05-16-dto-vs-vo-vs-entity/
✔️ 어려웠던 점, 새롭게 알게 된 점 💡
이번 우아한테크코스 2주차에서 가장 어려웠던 점은 도메인 구현과 테스트코드 작성이였다. 또한, 클래스를 설계하고 함수명을 정하는데 꽤 오랜 시간이 들었다. 다른 지원자분들 중 5시간 안에 구현하는 것을 목표로 하시는 분들이 계시던데 나도 얼른 분발해야할 것 같다,,, 새롭게 알게 된 점은 값 타입이다. 위 사항들은 아래 포스팅으로 따로 정리해두었다.
✔️ 2주차를 마치며
Spring, JPA등과 같은 기술을 사용하여 프로그램을 구현하는 것과 오직 자바에서 제공하는 API만 사용하여 구현하는 것은 확실히 차이점이 존재하는 것 같다. 우아한테크코스 프리코스를 하며 항상 느끼는 부분은 나는 아직 많이 부족하다는 것이다. 또한, 어떤 점이 부족한지 객관적으로 메타인지가 된다는 점이 우아한테크코스의 가장 큰 장점인 것 같다.(단점은 없다ㅎㅎ) 더 열심히 기록하고 더 많이 고민하는 습관을 가져야 할 것 같다. 또한 "왜?"라는 질문을 던지며 끊임없이 고찰하는 과정은 끝이 없고, 정답이 따로 정해져있지 않기 때문에 단순히 구현을 하는 것보다 더 어려운 것 같다는 생각이 들었다. 3주차부터는 테스트 코드를 더 정확하게 구현하는 것을 목표로 해야겠다. 또한, 항상 객체의 행위에 대해 물음표를 던지는 습관을 가져야겠다고 다짐했다. 남은 2주도 최선을 다하자!
'우아한테크코스 > 6기 프리코스' 카테고리의 다른 글
[우아한테크코스 6기 프리코스] 3주차 회고 (0) | 2023.11.09 |
---|---|
[우아한테크코스 6기 프리코스] 2주차 코드 리뷰 종합해보기! (0) | 2023.11.06 |
[우아한테크코스 6기 프리코스] 1주차 코드 리뷰 종합해보기! (2) | 2023.10.27 |
[우아한테크코스 6기 프리코스] 1주차 회고 (2) | 2023.10.26 |
[우아한테크코스 6기 프리코스] 1주차를 시작하기에 앞서 (2) | 2023.10.19 |