프리코스 2주차 회고록
우아한형제들의 개발자 양성 프로젝트, 우아한테크코스의 프리코스를 경험하게 된 것은 정말 뜻 깊은 시간이었습니다. 이 프리코스를 통해 많은 것을 배우고 성장하는 기회를 얻었습니다. 아래에는 이 경험에서 얻은 교훈과 느낀 점, 그리고 부족한 부분을 솔직하게 정리해보겠습니다.
🚀 기능 요구 사항
초간단 자동차 경주 게임을 구현한다.
- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
- 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
- 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
- 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
- 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.
입출력 요구 사항
입력
- 경주 할 자동차 이름(이름은 쉼표(,) 기준으로 구분)
pobi,woni,jun
- 시도할 회수
5
출력
- 각 차수별 실행 결과
"pobi : --
woni : ----
jun : ---"
- 단독 우승자 안내 문구
"최종 우승자 : pobi"
- 공동 우승자 안내 문구
"최종 우승자 : pobi, jun"
실행 결과 예시
"경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
pobi,woni,jun
시도할 회수는 몇회인가요?
5
실행 결과
pobi : -
woni :
jun : -
pobi : --
woni : -
jun : --
pobi : ---
woni : --
jun : ---
pobi : ----
woni : ---
jun : ----
pobi : -----
woni : ----
jun : -----
최종 우승자 : pobi, jun"
회고록
1. 다양한 입출력을 위한 Input, Output 인터페이스 분리
현재는 콘솔 기반의 입출력만 필요하지만 나중에 GUI 기반의 Swing이나 다른 형태의 입출력으로 확장할 가능성을 고려하여 Input과 Output을 인터페이스로 설계했습니다. 이를 통해 향후 다양한 입출력 방식을 손쉽게 통합할 수 있는 유연성을 확보하였습니다.
2.클래스의 역할과 책임에 대한 고민
처음에는 입력 클래스가 데이터를 읽는 것 뿐만 아니라 변환(Convert)하는 책임까지 갖게 할지 그리고 출력 클래스가 단순히 출력하는 것을 넘어서 형식을 맞추는(formatting) 역할까지 해야 하는지에 대한 고민을 했습니다. 하지 않는다면 입력에서 동일한 로직을 사용하는 숫자 입력 메소드와 자동차 이름 입력 메소드를 분리해야 하는지에 대한 고민도 많았습니다.
이러한 고민 끝에 클래스의 역할을 명확히 하기 위해 입력과 출력의 책임을 분리했습니다. 입력 클래스는 input()과 같은 메서드를 통해 데이터를 읽는 역할만 수행하고, 출력 클래스는 출력 형식에 맞춰 데이터를 보여주는 역할만 하도록 구현했습니다. 이는 Single Responsibility Principle(SRP)을 준수하여 각 클래스가 하나의 책임만 가지도록 함으로써 유지보수와 확장성을 향상시켰습니다.
3.일급 컬렉션 사용
자동차의 이름과 위치를 단순한 문자열과 숫자로 관리하는 대신 CarName과 CarPosition과 같은 객체로 감싸서 관리했습니다. 또한 List<Car> 대신 일급 컬렉션인 Cars 클래스를 통해 자동차 목록을 관리하였습니다. 이러한 접근은 객체 간의 관계를 더 명확히 하고 데이터의 무결성을 보장하며 비즈니스 로직을 컬렉션 내부에 숨길 수 있는 장점을 제공했습니다.
4.Factory Method 사용
Car 객체 생성시 CarName, CarPosition, MoveStrategy와 같이 여러 매개변수가 필요한 복잡한 생성 로직을 CarFactory를 통해 추상화했습니다. 이를 통해 객체 생성 과정에서의 유연성과 가독성을 향상시켰으며, 다른 타입의 Car 생성 요구사항이 생겼을 때 이를 쉽게 대응할 수 있게 되었습니다.
5. 다양한 전략 패턴 사용
자동차의 움직임을 결정하는 데 있어서 MoveJudgement 전략과 MoveStrategy 전략을 적용했습니다. MoveJudgement는 자동차가 움직일지 말지를 결정하는 로직으로 현재는 랜덤 값을 기준으로 판단하지만, 이를 다른 조건으로 쉽게 바꿀 수 있게 했습니다. 예를 들어 게임 난이도나 사용자의 입력에 따라 움직임을 결정하는 로직으로 변경할 수 있습니다. MoveStrategy는 자동차가 실제로 어떻게 움직일지를 정의합니다. 현재는 기본적으로 한 칸 전진하는 전략을 사용하지만 이 또한 다양한 전진 규칙을 적용할 수 있도록 유연하게 설계했습니다. 이를 통해 다른 전진 규칙을 적용하거나 움직임의 범위를 변경하고 싶을 때 추가적인 전략을 쉽게 통합할 수 있습니다.
이렇게 두 가지의 전략 패턴을 사용함으로써 자동차의 움직임을 제어하는 방식이 매우 유연해지고 미래의 변경 사항에 대해 쉽게 확장하거나 수정할 수 있는 구조를 만들었습니다.
6.오버엔지니어링에 대한 고민
설계 과정에서 클래스가 40개에 이를 정도로 많아졌는데 이는 요구사항을 넘어서는 오버엔지니어링된 설계가 아닐까라는 고민을 하게 되었습니다. 현재의 요구사항에만 집중하여 빠른 개발과 실행을 우선할지 아니면 장기적인 확장성과 유지보수를 고려한 설계를 할지에 대해 많은 고민을 했습니다. 1주차와 2주차 과제를 생각해 봤을때 다양한 게임을 선택, 혹은 섞어서 사용한다고 하면 지금의 설계가 맞다고 생각이 들었고 장기적인 확장성과 유지보수에 초점을 맞춘 설계를 선택했습니다.
이러한 설계와 구조에 대한 깊은 고민은 저에게 많은 도움이 되었습니다. 비록 클래스의 수가 많아지고 복잡성이 증가했지만 이를 통해 시스템의 확장성과 유지보수성에 대해 보다 깊이 이해할 수 있었고 설계에 대한 더 광범위한 관점을 가질 수 있게 되었습니다!
앞으로의 3주차와 4주차 과제에서는 이러한 학습이 실제로 어떻게 적용되고 성과를 낼 수 있는지를 보여드릴 기회가 될 것입니다. 계속해서 성장하고 더 나은 소프트웨어 개발자로 거듭나는 모습을 보여드리겠습니다.감사합니다!
코드도 한번씩 봐주시면 감사하겠습니다! 잘못된 부분 말해주시면 수정하겠습니다!
코드보기
https://github.com/woowacourse-precourse/java-racingcar-6/pull/1155
[자동차 경주 게임] 김태훈 미션 제출합니다. by xogns4909 · Pull Request #1155 · woowacourse-precourse/java-rac
🗃 구현기능 📝 문자열 처리 유틸리티 1.1 문자열 형식 검증 : 정규식을 이용해 입력된 문자열이 문자와 ,로만 구성되었는지 검증합니다. 1.2 문자열을 문자열 리스트로 변환 : 입력된 문자열을
github.com
파일구조
🗂 폴더 구조
🛠 util
- 🛡️ validator
- 📝 StringLengthValidator: 자동차 이름 길자 수 검증
- 📝 RegexValidator: 자동차 이름 형식 검증
- 🔄 converter
- 📝 StringToNumberConverter: 문자를 숫자로 변환
- 📝 StringToStringListConverter: 문자열을 리스트로 변환
- 📝 StringListToCarListConverter: 문자열 리스트를 자동차 리스트로 변환
- 🎰 generator
- 📝 NumberGenerator: 0~9 사이의 랜덤 값 생성
- 🎨 formatter
- 📝 RoundResultFormatter: RoundResultDto 출력 형식 변환
- 📝 WinnerFormatter: WinnerDto 출력 형식 변환
🏢 domain
- 🚗 Cars: 자동차들의 정보를 저장
- 🚖 Car: 자동차의 움직임 관리
- 📝 CarName: 자동차 이름 저장
- 📝 CarLocation: 현재 자동차 위치 저장
- 🚀 MoveJudgement: 자동차 전진 가능 여부 인터페이스
- 📝 RandomMoveJudgment: MoveJudgement 구현
- 📝 MoveStrategy: 자동차 움직임 전략 인터페이스
- 📝 OneStepMoveStrategy: MoveStrategy 구현
🚥 Controller
- 📝 CarRacing: Racing 구현
- 📝 Racing: 여러 레이싱을 위한 인터페이스
👀 view
- 📥 input
- 📝 Input: 입력 인터페이스
- 📤 output
- 📝 Output: 출력 인터페이스
- 🖼️ ConsoleInputView: Input 인터페이스 구현
- 🖼️ ConsoleOutputView: Output 인터페이스 구현
📝 dto
- 📝 RoundResultDto: 각 경기 결과 기록 DTO
- 📝 WinnerInfoDto: 우승자 기록 DTO
🔈 enum
- 📝 RaceMessages: 출력 메세지 상수 이넘
'우아한 프리코스' 카테고리의 다른 글
[우아한 테크 코스]6기 프리코스 4주차 회고록 (0) | 2023.11.24 |
---|---|
[우아한 테크 코스]6기 프리코스 3주차 회고록 (0) | 2023.11.23 |
[우아한 테크 코스]6기 프리코스 1주차 회고록 (0) | 2023.10.25 |