[개발 기록] Racingcar
자동차 경주
꼭 지켜야 할 사항
- [] 테스트
- [] 자바 code convention을 지키기
- [] 메소드를 분리
- [] 예외를 사용하라
기능 요구사항
- [] 횟수가 주어진다. (라운드 진행 개수)
- [] n대의 자동차의 개수를 입력할 수 있다. (참여자 수)
- [] 자동차는 전진 또는 멈출 수 있다. (자동차)
- [] 자동차는 0에서 9 사이의 랜덤 값을 매 라운드 추첨한다.
- [] 랜덤 값이 4이상이면 전진, 아니면 정지이다.
- [] 라운드마다 자동차의 상태를 출력한다.
프로그래밍 요구사항
- [] InputView, ResultView 와 같은 UI 클래스를 따로 분리한다.
- [] 모든 로직에 단위 테스트를 구현한다.
- [] 자바 코드 컨벤션을 지키면서 프로그래밍한다.
기능 순서도
- 사용자에게 자동차 개수를 입력 받는다. (IntputView)
- 개수만큼 자동차가 생성된다. (Car, Cars)
- 사용자에게 횟수를 입력 받는다. (IntputView)
- 횟수만큼 라운드가 생성된다. (Rounds)
- 라운드를 진행한다. (Round)
- 차가 전진하거나 정지한다. (Car, Movement)
- 라운드 결과 판단. (Round, Score, ScoreBoard)
- 라운드 결과를 저장. (Round, ScoreBoard)
- 라운드 결과를 출력한다. (Round, OutputView)
- 라운드가 끝났는지 판단한다. (GameBoard, Rounds)
- 라운드가 끝날 때까지 반복. (GameBoard)
클래스들
Car : 자동차
- 자동차를 움직인다.
- 자동차의 움진인 결과를 전달한다. (to Round) RandomGenerator
- 랜덤값을 생성한다. Round
- 라운드를 진행한다.
- 라운드의 결과를 판단한다. (to Score)
- 라운드의 결과를 전달한다. (to ScoreBoard) Score
- 자동차의 점수를 보관한다.
- 자동차의 점수를 판단한다. ScoreBoard
- 라운드의 결과를 저장한다.
지켜야할 객체지향 원칙
- 일급 컬렉션
- 비지니스에 종속적인 컬렉션 객체를 만들 수 있습니다.
개발 하면서 느낀 문제점
- 의존성과 테스트 가능한 코드.
RandomGenerator라는 랜덤 값에 의존하다 보니 원하는 테스트가 안된다.
아래처럼 자동차의 움직이는 여부는 랜덤 값이 4이상일때인데 랜덤이다보니 원하는 테스트가 되지 않습니다.
여러가지 고민하다 Success 하는 경우와 Fail의 경우 2가지 stub을 제작했습니다.
@DisplayName("자동차가 전진합니다.") @Test void a(){ assertThat(car.decideMovement()).isTrue(); } @DisplayName("자동차가 정지합니다.") @Test void b(){ assertThat(car.decideMovement()).isFalse(); }
``` private int pickRandomeValue() { return randomGenerator.number(); }
public boolean decideMovement() { return pickRandomeValue() > MOVE_CONDITION; }
2. 클래스 하나에 대한 테스트를 진행하기 어려움
위 문제점과 어느정도 연관성이 있다고 판단됩니다.
아래 테스트의 가장 큰 문제점은 `Round`클래스를 테스트하는 것임에도 `ScoreBoard`를 순회하면서 테스트를 수행하고 있다는 점입니다.
이게 `Round`인지 `ScoreBoard`인지 짬뽕 되어 버렸습니다.
```java
@DisplayName("라운드가 정상 진행 - 차가 움직임")
@Test
void roundRacingWhenCarMoving(){
Round round = new Round(movingCars);
ScoreBoard scoreBoard = new ScoreBoard();
assertThatNoException().isThrownBy(() -> round.race(scoreBoard));
scoreBoard.scores().forEach(score -> {
score.keySet().forEach(car -> {
assertThat(car.canMove()).isEqualTo(MoveStatus.MOVE);
});
});
}
궁금한 점
- side effect란?
- 뭐가 side effect인가?
자동차 경주 2
요구사항
- 각 자동차에 이름을 부여할 수 있다. 자동차 이름은 5자를 초과할 수 없다.
- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- 자동차 이름은 쉼표(,)를 기준으로 구분한다.
- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한명 이상일 수 있다.
- 자동차 수를 입력 받는다.
- 라운드 수를 입력 받는다.
- 입력 값만큼 차를 생성한다.
- 랜덤 값을 생성한다.
- 랜덤 값이 0에서 9 사이의 값이 아닐 경우, 에러가 발생한다.
- 랜덤 값이 전진 조건(4이상)에 해당하는지 확인한다.
- 자동차는 전진 조건에 따라 전진 또는 정지한다.
- 화면에 결과를 출력한다.
자동차 경주 3
기술 요구사항
view 패키지의 객체가 domain 패키지 객체에 의존할 수 있지만 domain 패키지의 객체는 view 패키지 객체에 의존하지 않도록 구현한다
댓글남기기