-
Notifications
You must be signed in to change notification settings - Fork 908
[자동차 경주] 이예림 미션 제출합니다. #922
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
kwonhee1
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.
README를 정말 상세하게 작성하셔서 리뷰하기 좋았어요
| public List<Car> getCars() { | ||
| return cars; | ||
| } | ||
| } |
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.
순서에 대한 안정성을 위해 Cars 객체를 따로 만든 부분이 좋은 것 같아요
| return new Car(name, location + 1); | ||
| } | ||
| return this; | ||
| } |
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.
move 할 때 마다 Car와 Cars 객체를 새로 찍어서 반환한 이유가 긍금합니다
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.
불변 객체로 만들고 싶다는 마음에 메모리는 많이 들지만 new를 사용해서 코드를 구성했습니다. 이번 요구 사항에 함수형 설계가 중점으로 나와있어서 불변 객체로 진행하여 함수가 항상 예측 가능하게 동작할 수 있도록 하였습니다. 가변 객체가 되면 외부 상태에 따라 객체의 결과가 변경될 가능성이 높다고 배워 그렇게 진행하였습니다. 좋은 질문 감사합니다😊
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.
숫자 상수 하나 하나까지 정의해서 사용한거 보니 반성이 많이 되네요
✅ 기본 조건
입력 조건
IllegalArgumentException을 발생 후 종료되어야 함자동차 이름
,기준으로 구분경주 차수
동작 조건
출력 조건
,기준으로 구분pobi : --)최종 우승자 : pobi),를 기준으로 출력 (ex최종 우승자 : pobi, jun)✅ 구조 설정 이유
의존성 방향
[Application] ↓ [Controller] → [View] ↓ [Service] ↓ [Domain] ↑ [Mapper] → [DTO]단일 책임 원칙과 의존성 역전 원칙, 유지보수 용의성을 고려하여 설계하고자 했습니다.
-
Controller → Service → Domain의 단방향 의존 구조를 통해, 상위 계층이 하위 계층의 세부 구현에 의존하지 않도록 하였습니다. 즉, Domain은 Controller나 View를 몰라도 되고, 변경에 영향을 받지 않습니다. Mapper는 Domain 객체를 DTO로 변환하는 역할만 수행하며, DTO는 View와 Controller에 전달되는 데이터 구조로 사용됩니다.패키지 별 보유 클래스
Domain에는 이 프로젝트가 해결하고자 하는 본질적인 문제를 표현하는 부분을 담았습니다.Car,Cars자동차 및 여러 자동차를 관리하는 로직,WinnerCalculator게임의 결과를 계산하는 핵심 로직,MovePolicy,RandomMovePolicy전진의 조건을 계산하기 위한 게임의 규칙 로직을 구현해두었습니다.Service는 각 도메인 객체를 조합해서 각 로직의 실행 흐름을 구현해 두었습니다. 입력을 받아Cars객체로 만드는 initCars 메서드, 입력값의 유효성을 검증하는 validate 메서드들,MovePolicy에 따라Cars내부 메서드를 통해 진행하는 경주에서의 자동차 전진 위치 증가 playRound 메서드,WinnerCalculator의 static 메서드를 통해 진행하는 이긴 자동차 리스트 받아오는 getWinners 메서드로 구성되어 있습니다.View를 통해 입력과 출력의 형식만 담당하여InputView와OutputView를 구성하였습니다. 따로 입출력을 위해 필요한String리소스는ViewMessagesEnum클래스로 관리하고 있습니다.Controller를 통해 입력 > 서비스 실행 > 출력 프로그램의 전체 흐름을 제어하였습니다. 따라서 RacingController의 run 메서드를 통해 이 프로젝트가 실행되는 흐름을 확인할 수 있습니다.그 외로
error와util패키지를 통해 예외 메세지 관리, 랜덤 수 생성을 진행하고 있습니다. 마지막으로dip의존성 역전 원칙 위배를 보완하기 위해dto와mapper를 통해dto로controller와view사이에서 객체 데이터를 주고 받도록 설정하였습니다.✅ 예외 조건 설정 및 이유
자동차 이름
이름, ,이름의 경우 사용자의 실수일 수 있지만 앞선 요구사항에서,로 이름을 구분하라는 부분과 자동차 이름은 1자 이상과 5자 이하만 가능하다는 분석에 입각해 공백 시 예외를 발생 시키고자 하였습니다.Car클래스에equal과hashCode메서드를 오버라이드하여 이름이 같다면 같은 객체로 처리하도록 하여 부가적인 문제를 원천 차단하였습니다.경주 차수
NumberFormatException이 발생하는 경우)✅ 테스트
JUnit 5와 AssertJ를 이용하여 테스트 코드를 작성하였습니다. 작성한 코드가 단위 별로 잘 돌아가는지 단위 테스트를 진행하였으며, 제공된 2개의 테스트 이외의
CarTest,CarsTest,RandomMovePolicyTest,WinnerCalculatorTest,RacingServiceTest로 20개의 테스트를 진행했습니다.✅ 고민한 점
1.
RandomMovePolicy의 위치직접
RandomMovePolicy를 참조하지 않고MovePolicy를 참조하게 하여 구체 구현체를domain단에서 직접 참조하지 않도록 설정해 DIP 규칙을 준수하게 하였습니다. 다만, 현재는MovePolicy의 다양한 구현이 예측되지 않기에domain패키지에 위치시켰습니다.2. 입력값 유효성 검증을 위한
validate함수들 위치입력값에 대한 유효성을 검증한다는 것은 맞지만, 구조에 맞춰서 왜 이 시점에서, 해당 대상에게, 관련 내용을 유효성을 검증해야 하는지에 대해 잘 드러나도록 검사하고자 노력했습니다.
3.
List<Car>이 아닌Cars클래스 설정 이유이번 프로젝트를 진행하면서 일급 컬렉션(First-Class Collection) 개념을 알게 되었습니다. 단순히
Car객체만 사용하는 것보다,List<Car>를 직접 사용하는 경우 컬렉션이 외부에서 자유롭게 변경될 수 있어 안전성 문제를 고민하게 되었습니다. 특히, 자동차 경주 우승이 1명으로 특정 되지 않을 때, 입력 순서대로 출력해야 하는 조건을 고려해야 했기에 이가 중요히 여겨졌습니다.따라서 이를 해결하기 위해
Cars클래스로 컬렉션을 감싸고, 컬렉션 관련 로직(전진, 우승자 계산 등)을 해당 클래스 안에서 처리함으로써 불변성을 유지하고, 보다 안전하고 깔끔한 코드를 구현할 수 있었습니다.