Projects/Remembrance

[회고] 우테코 프리코스 2주차 - 자동차 경주

YongE 2024. 11. 4. 00:29

🌍과제 - 자동차 경주


 

사용자에게 경주 횟수를 받아서 횟수만큼 경주를 진행하여 가장 많이 전진한 자동차가 승리하는 프로그램을 구현하는 것이다.

 

 

❗구현 기능 목록

  • 자동차 생성 기능
    • 자동차 이름은 쉼표(,)를 기준으로 구분
    • 이름은 5자 이하만 가능
  • 전진 여부 판단 기능
    • 4 이상일 경우에만 전진
  • 경주 진행 및 우승자 선정 기능
    • 시도횟수만큼 경주 진행
    • 각 자동차의 전진 여부 저장
    • 경주가 끝나면 우승자 선정
  • 사용자 입력 및 결과 출력 기능
  • 경주 진행 관리 기능

 

회고


테스트 코드를 적절하게 작성할 수 있도록 해야겠다.

@ParameterizedTest
@ValueSource(ints = {10, 20, 100})
void 시도횟수만큼_경기를_진행하면_모든_자동차의_전진횟수가_같지_않다(int round) {
    // given
    racingCarGameAfter = new RacingCarGame(carFactory.extractCarNames("pobi,yongE,java,twerk"));
    racingCarGameBefore = new RacingCarGame(carFactory.extractCarNames("pobi,yongE,java,twerk"));
    // when
    for (int i = 0; i < round; i++) {
      racingCarGameAfter.play();
    }
    // then
    Assertions.assertThat(racingCarGameAfter.cars().stream().map(Car::getMoveCount)).isNotEqualTo(racingCarGameBefore.cars().stream().map(Car::getMoveCount));

  }

 

1~9까지의 랜덤숫자를 생성해 4 이상이면 전진, 이하면 정지로 판단한다. 여기서 중요한 것은 랜덤을 테스트해야 한다는 것이다. 자동차 전진 혹은 정지를 판단하는 기능은 테스트를 해야 하는데 "랜덤이란 부분을 어떻게 단위 테스트로 작성하지?"란 고민이 많았다. 그래서 작성한 코드가 위와 같은데 다시 보고 나서야 적절하지 못하다는 것을 깨달았다. "시도 횟수만큼 경기를 진행하면 모든 자동차의 전진횟수가 같지 않다"고 정의했다. 생성되는 자동차는 3개이고, 각각 랜덤을 10번, 20번, 100번씩 돌려서 각 자동차의 전진이나 정지를 결정한다. 그리고나서 각 자동차의 전진횟수를 비교한다. 그런데 여기서 문제는 만약 10번씩 랜덤을 돌려서 전부 4 이상의 숫자가 나온다면? 모든 자동차의 전진횟수는 똑같다. 20번, 100번 돌리면 확률은 단연코 매우 낮아지겠지만 전진횟수가 동일할 수도 있지 않겠는가? 그러니 이는 적절한 단위 테스트가 아니라고 생각한다. 랜덤 숫자를 인위적으로 정해서 전진 및 정지 판단 기능을 테스트 하는 게 더 나은 테스트가 아니었을까 한다.

랜덤 테스트에 대한 내용은 다음 글을 참고하면 좋겠다.

 

 

문서 작성에 대한 고민

## 🚗 구현 기능 상세 설명

---

### 자동차 생성 기능
> 입력된 값을 쉼표로 구분해 갯수만큼 자동차를 생성하는 기능이다. 전체 자동차는 Car 객체로 생성된다.

**예외 발생**

파라미터 단계
- [ ] 입력된 문자열에 쉼표(,)가 아닌 구분자가 있을 경우 (ex pobi.con@kim)
- [ ] 쉼표가 연속으로 입력될 경우 (ex woo,,te,co)
- [ ] 쉼표 다음으로 잘못된 구분자가 입력될 경우 (ex pobi,.teco) 

메소드 단계
- [ ] 입력된 자동차 이름이 5자를 초과할 경우 (ex kimwoo,teccobi)
- [ ] 입력된 자동차 이름이 없을 경우 (ex  "" or ,)
- [ ] 입력된 자동차 이름이 중복될 경우 (ex pobi,pobi)
- [ ] 자동차가 하나밖에 없을 경우 (ex pobi)

_고민한 부분_
- 쉼표 다음으로 오는 character도 자동차 이름으로 인정해줘야 하는가?
  - f!ve나 ㅋold 같은 경우는 센스 있는 이름이라고 여겨질 수 있다. 다만 점(.)으로 시작한다거나 특수문자 하나만 있는 경우는 인정해주기 난감하다. 따라서 이 부분은 이전 프리코스에서 회고한 부분인 '정규표현식'을 사용하기로 했다.
- 경주에 참가하는 자동차가 하나여도 되는 걸까?
  - 자동차 경주이지, 독주가 아니기 때문에 유일한 참가는 성립하지 않는다고 생각한다.
- 모든 예외 상황을 발생시키기 위해 위의 조건을 전부 정규표현식으로 변환한다면 지나치게 길다.
  - 따라서 입력된 직후 구분자에 대한 예외만 정규표현식으로 검사하고, 나머지는 메소드로 유효성 검사를 실시하는 것으로 진행한다. 

---


### 경주 진행 및 우승자 선정 기능
> 사용자에게 입력된 시도 횟수만큼 자동차 경주를 시도한 결과를 저장한다. 경주가 끝나면 우승자의 이름을 추출한다.

**예외 발생**
- [ ] 시도 횟수가 0 이하일 경우
- [ ] 시도 횟수가 양수가 아닌 경우 (ex -1 or 0 or 삼)
- [ ] 전진 횟수가 전부 0일 경우

_고민한 부분_
- 모든 자동차가 한 번도 움직이지 않았을 때도 우승으로 해야 하는가?
  - 경주의 의미를 생각해봤을 때 모든 자동차가 한 번도 움직이지 않았다면 경주를 하는 것이 아니기에 예외로 처리한다.

---

 

각 기능 별 예외상황과 고민한 부분을 작성했다. 이런 방식으로 하면 기능별로 예외 처리를 상세히 할 수 있고, 수정한 부분을 문서에 자주 반영하도록 할 수 있다. 그런데 어떤 예외 상황은 다른 기능에서 처리해야 할 때도 있고, 고민한 부분은 작성하는 것까진 좋았으나 모든 부분이 굳이 문서에 넣을 만큼 필요한 부분이었을까? 라는 의문이 남는다. 또 이러면 기능 자체를 수정하거나 첨삭할 때 분명히 그 아래 내용도 대대적인 수정을 해야 할 것이다. 따라서 이런 건 좋은 문서 작성법이 아닌 것 같다. 다음에는 기능과 예외 상황을 분리해서 작성하는 방식으로 시도해봐야겠다.

728x90
반응형