- JUnit5, assertJ 를 사용한 단위테스트
- 테스트 의도를 명확히 드러내는 테스트 네이밍 컨벤션
- 실패하는 테스트 > 성공하는 테스트 > 리팩토링 3단계의 테스트 사이클 적용
- 값객체를 사용하여 객체의 조건을 보장하는 역할을 위임
- 상태와 로직을 따로 관리할 수 있는 일급 컬렉션의 사용
- 테스트하기 어려운 값(ex.Random)에 대한 의존을 역전시켜 특정 구현에 의존하지 않고 테스트하기 쉬운 코드로 변경
- 매직 넘버에서 의미있는 상수로 변환하기
- 유지보수성을 고려하여 메서드가 한가지 역할을 할 수 있도록 메서드 분리
- 자동차 경주 게임 요구사항을 파악한다.
- 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.
- 코드 리뷰 피드백에 대한 개선 작업을 하고 다시 PUSH한다.
- 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.
- 빈 문자열 혹은 null 값을 입력할 경우 0을 반환한다. ("" => 0, null => 0)
- 숫자 하나를 문자열로 입력할 경우 해당 숫자를 반환한다. ("1" => 1)
- 쉼표 혹은 콜론을 구분자로 가지는 문자열을 전달하는 경우, 구분자를 기준으로 분리한 각 값의 합을 반환한다. ( "1,2:3" => 6)
- 문자열 계산기에 숫자 이외의 값 또는 음수를 전달하는 경우, RuntimeException 예외 throw한다. ("-1:2:3" => RuntimeException)
- 커스텀 구분자를 지정할 수 있다. ("//;\n1;2;3" => 6)
- junit4 의존성 삭제
- 유닛 테스트 네이밍 코드 컨벤션 적용
- 한 번만 수행해도 되는 코드 분리 (Patter.compile / split)
- 양수임을 보장하는 값 객체를 활용한 숫자 이외의 값 혹은 음수 검증
- Array => List 변경
- ParameterizedTest를 활용한 여러 개의 테스트 수행
- 객체를 만들었다면 객체간 소통이 되도록 작성해보기(PositiveNumber class)
- 반환 값을 PositiveNumber로 하여 반환값을 보장하고, 생성자에서 예외를 던지도록 변경
- README.md 파일에 구현할 기능 목록을 정리한다.
- git commit 단위는 아래 정리한 기능 목록 단위로 추가한다.
- Java 코드 컨벤션을 지키면서 프로그래밍한다. (IntelliJ idea Code Style.java)
- else 예약어를 쓰지 않는다.
- UI 로직을 제외한 모든 로직에 단위 테스트를 구현한다.
- 핵심 로직 구현 코드와 UI 담당 로직을 구분한다.
- UI 로직은 별도 클래스를 추가해 분리한다. (InputView, ResultView)
- 자동차 대수와 횟수를 사용자에게 입력받는다. (3, 5)
- 자동차 대수만큼 자동차를 생성한다.
- 전진 조건은 랜덤 값을 구해 4 이상인 경우이다.
- 각 자동차는 멈추거나 전진한다,(움직인다)
- 결과를 화면에 출력한다. 출력 시점의 제약은 없다.
- 사용자 입력을 받기 위해 InputView를 매번 생성하는 것이 아닌, 필요한 정보를 얻을 수 있는 메서드를 별도 구현
- 애플리케이션이 실행되는 main의 구조 변경
- RacingCar에 static으로 구현된 메서드를 모두 별도의 클래스로 옮겨 각자 책임을 부여
- List 타입 변수를 CarList라는 일급 컬렉션으로 변경해서 관리
- 전체적으로 OOP의 개념에 입각해 여러 객체를 도출하고 객체간 메시지를 주고받으며 협력하도록 구조 개선
- 일급 컬렉션 CarList의 클래스명을 컬렉션 성격을 드러내지 않도록 변경한다.
- InputView에서 사용자에게 입력받은 값을 InputView의 멤버변수, 정적변수로 두면 객체 재활용 시 문제가 됨. InputView에게 필요한 변수를 얻는 메서드로 구현하자.
- 콘솔에서 출력하는 부분은 언제든지 바뀔 수 있으므로, CarList 내 ResultView 부분은 모두 제거하고, CarList에게 얻은 값을 ResultView에게 전달하도록 구현
- ResultView 외 위치한 println()의 위치 변경
- 현재 자동차 생성 시 CarList 생성 후 addCar, moveByTryCount의 순서가 보장되지 않는다. 팩터리 메서드를 이용해 CarList를 생성할 때 미리 Car객체를 생성하도록 해보자.
- 현재 작성한 Car.move()의 결과값 범위 테스트보다는, 확실한 상태에 대한 Test를 작성하자. 의존성 역전에 대해 알아보고 적용해볼 것.
- CarList.moveByTryCount()에 대한 Test도 위에 언급한 바와 같다. 확실한 상태값에 대한 테스트를 진행하고, for loop / if-else와 같은 반복, 조건문을 지양한다.
- 테스트 삭제
- getRandomNumber() Test는 굳이 필요가 없을 듯 하다.
- 의존성 역전을 통해 핵심 메서드인 move() 개선 + InputView, ResultView
- 현재 addCar()는 직접 제어할 수 없는 상태(테스트하기 힘들다.) 추후 개선 요망
- indent depth는 2가 넘지 않도록 구현한다.
- 함수 길이가 15라인을 넘어가지 않도록 구현한다.
- 각 자동차의 이름을 부여할 수 있다.
- 자동차 이름은 5자를 초과할 수 없다.
- 자동차 이름은 쉼표를 기준으로 구분한다.
- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- 자동차 게임을 완료한 후 누가 우승했는지를 알려준다.
- 우승자는 여러명일 수 있다.
- Car의 원시값 name을 포장한 CarName 클래스 추가
- move의 이동 조건인 랜덤값 3 초과에서 '3'을 상수로 변환
- Winners 객체의 우승자 선정 역할을 Cars가 하도록 변경
- 우승자 선정 로직 수정
- RacingCarGame 내 일부 멤버변수 -> 지역변수 위치 이동
- RacingCar moveOnce() 결과 callback 함수로 호출
- RacingGameRequest 역할 분리
- Cars 생성은 Cars 역할로 분리