Skip to content

1주차 - Step2 자동차 경주 구현 #319

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

Merged
merged 27 commits into from
Jun 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0a1c04e
docs #step2 - 구현할 기능 목록 추가
Integerous Jun 17, 2019
1bce695
feat #step2 - 사용자로부터 값을 입력받고 출력하는 main 메서드 추가
Integerous Jun 17, 2019
303459f
refactor #step2 - Main 메서드의 UI 로직을 InputView로 분리
Integerous Jun 17, 2019
29901aa
feat #step2 - Car 클래스 추가, 기능구현계획 수정
Integerous Jun 18, 2019
c2597d3
test #step2 - Car 유닛테스트 추가, Car 클래스의 move() 메서드 수정
Integerous Jun 18, 2019
acd03f3
feat #step2 - 사용자 입력값 Validation 추가
Integerous Jun 18, 2019
cef19ce
refactor #step2 - Scanner를 생성자로 초기화하도록 수정
Integerous Jun 18, 2019
e4fa12b
feat #step2 - 자동차들을 생성하고 화면에 출력
Integerous Jun 18, 2019
808574d
feat #step2 - 전진 여부를 결정하는 로직 추가(리팩토링 필요)
Integerous Jun 18, 2019
1d55df4
feat #step2 - 시행 횟수만큼 자동차를 전진시키는 메서드 추가, 각 시행마다 화면에 출력
Integerous Jun 18, 2019
9a8150f
refactor #step2 - 자동차 이동 테스트 로직 변경
Integerous Jun 18, 2019
c848ead
refactor #step2 - 경주를 실행하는 RaceExcutor 클래스 분리
Integerous Jun 18, 2019
c702fcf
refactor #step2 - 패키지 분리(domain, utils, view)
Integerous Jun 18, 2019
9188b75
refactor #step2 - 자동차의 전진 여부를 결정하는 로직을 MoveIndicator 클래스로 분리
Integerous Jun 18, 2019
3f5431f
feedback #step2 - CarTest의 @BeforEach 대신 Car 객체 인스턴스화
Integerous Jun 18, 2019
ff8683b
feedback #step2 - 일급 컬렉션 객체(Cars) 생성, CarRace 클래스에 Cars 사용
Integerous Jun 18, 2019
522d860
feedback #step2 - Car 객체가 자동차의 이동가능 여부 가지도록 수정
Integerous Jun 18, 2019
e9b8399
feedback #step2 - Cars 컬렉션을 Cars에서 생성하도록 변경, 게임 시작 메서드 변경
Integerous Jun 18, 2019
e62c955
feedback #step2 - NumberGenerator 인터페이스 생성
Integerous Jun 18, 2019
ea19507
feedback #step2 - 자동차들 이동 로직을 Cars 클래스로 이전, 각 경주 시행결과 반환을 main 메서드로 이전
Integerous Jun 18, 2019
3334a79
feedback #step2 - numberOfTrials를 main메서드에서만 사용
Integerous Jun 18, 2019
7b3fa9e
feedback #step2 - NumberGenerator를 CarRace의 필드로 사용
Integerous Jun 18, 2019
5cd9174
feedback #step2 - printEmptyLine() 추가, 출력과 관련된 것을 OutputView에 위임
Integerous Jun 18, 2019
846a85a
feedback #step2 - Cars를 OutputView의 메서드로 전달하도록 수정
Integerous Jun 18, 2019
afdd1e6
feedback #step2 - InputView의 입력값 검증 로직을 CarRace 클래스로 이전
Integerous Jun 18, 2019
7928fad
feedback #step2 - (오류 수정) numberGenerator 초기화 및 전달 범위 수정
Integerous Jun 18, 2019
48612a7
feedback #step2 - 테스트코드 //TODO 세팅
Integerous Jun 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,17 @@
* 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.

## 온라인 코드 리뷰 과정
* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)
* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)

## 구현할 기능 목록

### step2
- [x] 사용자가 몇 대의 자동차로 몇 번의 이동을 할 것인지 입력하는 기능
- [x] (추가) 자동차의 속성 정의
- [x] 입력받은 자동차 수에 따라 자동차를 생성하는 기능
- [x] 생성된 자동차를 화면에 출력하는 기능
- [x] 자동차의 전진 여부를 무작위으로 결정하는 기능
- [x] 자동차가 전진 할 경우 화면에 출력될 변화를 설정하는 기능
- [x] 입력받은 실행 횟수에 따라 경주를 실행하는 기능
- [x] 실행 결과를 화면에 출력하는 기능
- [ ] (추가) 구조 리팩토링
27 changes: 27 additions & 0 deletions src/main/java/step2/CarRaceApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package step2;

import step2.domain.CarRace;
import step2.domain.Cars;
import step2.view.InputView;
import step2.view.OutputView;

public class CarRaceApplication {

private static CarRace carRace;

public static void main(String[] args) {
InputView inputView = new InputView();
final int numberOfCars = inputView.getNumberOfCars();
final int numberOfTrials = inputView.getNumberOfTrials();

carRace = CarRace.raceStart(numberOfCars, numberOfTrials);

OutputView outputView = new OutputView();
outputView.showResultTitle();
for (int i = 0; i < numberOfTrials; i++) {
Cars raceResult = carRace.executeTrials();
outputView.showResult(raceResult);
}
}

}
27 changes: 27 additions & 0 deletions src/main/java/step2/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package step2.domain;

public class Car {
private final static int INITIAL_POSITION = 0;
private final static int DISTANCE_PER_MOVE = 1;
private final static int MOVE_CRITERION = 4;
private int position;

public Car() {
this.position = INITIAL_POSITION;
}

public int getPosition() {
return position;
}

public int move(int randomNumber) {
if (canMove(randomNumber)) {
return position += DISTANCE_PER_MOVE;
}
return position;
}

private boolean canMove(int randomNumber) {
return randomNumber >= MOVE_CRITERION;
}
}
39 changes: 39 additions & 0 deletions src/main/java/step2/domain/CarRace.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package step2.domain;

import step2.utils.NumberGenerator;
import step2.utils.RandomNumberGenerator;

public class CarRace {

private final static int MINIMUM_NUMBER_CAN_BE_INPUT = 1;
private Cars cars;
private NumberGenerator numberGenerator;

private CarRace(Cars cars) {
this.cars = cars;
numberGenerator = new RandomNumberGenerator();
}

public static CarRace raceStart(int numberOfCars, int numberOfTrials) {
numberOfCarsValidation(numberOfCars);
numberOfTrialsValidation(numberOfTrials);
return new CarRace(Cars.makeCars(numberOfCars));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정적 팩토리 메서드를 사용하셨네요! 👍

}

public Cars executeTrials() {
return cars.moveCars(numberGenerator);
}

private static void numberOfCarsValidation(int numberOfCars) {
if (numberOfCars < MINIMUM_NUMBER_CAN_BE_INPUT) {
throw new IllegalArgumentException("최소 1대의 자동차가 필요합니다.");
}
}

private static void numberOfTrialsValidation(int numberOfTrials) {
if (numberOfTrials < MINIMUM_NUMBER_CAN_BE_INPUT) {
throw new IllegalArgumentException("최소 1번의 시행 횟수가 필요합니다.");
}
}

}
36 changes: 36 additions & 0 deletions src/main/java/step2/domain/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package step2.domain;

import step2.utils.NumberGenerator;

import java.util.ArrayList;
import java.util.List;

public class Cars {

private List<Car> cars;

private Cars(List<Car> cars) {
this.cars = cars;
}

public List<Car> getCars() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return cars;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DTO를 사용하지 않는다면 값을 getter하는 부분에서 read-only 혹은 불변객체로 리턴하는 것이 좋다고 생각합니다.

https://www.geeksforgeeks.org/collections-unmodifiablelist-method-in-java-with-examples/

}

public static Cars makeCars(int numberOfCars) {
List<Car> cars = new ArrayList<>();
for (int i = 0; i < numberOfCars; i++) {
cars.add(new Car());
}
return new Cars(cars);
}

public Cars moveCars(NumberGenerator numberGenerator) {
for (Car car : cars) {
car.move(numberGenerator.getRandomNumber());
}
return this;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일급 콜렉션은 불변성을 보장해야 합니다.

https://jojoldu.tistory.com/412

}


}
6 changes: 6 additions & 0 deletions src/main/java/step2/utils/NumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package step2.utils;

public interface NumberGenerator {

int getRandomNumber();
}
13 changes: 13 additions & 0 deletions src/main/java/step2/utils/RandomNumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package step2.utils;

import java.util.Random;

public class RandomNumberGenerator implements NumberGenerator {
private final static int LIMIT_OF_RANDOM_NUMBER = 10;

@Override
public int getRandomNumber() {
Random random = new Random();
return random.nextInt(LIMIT_OF_RANDOM_NUMBER);
}
}
31 changes: 31 additions & 0 deletions src/main/java/step2/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package step2.view;

import java.util.Scanner;

public class InputView {
private final static String ASK_NUMBER_OF_CARS = "자동차 대수는 몇 대 인가요?";
private final static String ASK_NUMBER_OF_TRIALS = "시도할 횟수는 몇 회 인가요?";
private Scanner scanner;

public InputView() {
this.scanner = new Scanner(System.in);
}

public int getNumberOfCars() {
System.out.println(ASK_NUMBER_OF_CARS);
return scanner.nextInt();
}

public int getNumberOfTrials() {
System.out.println(ASK_NUMBER_OF_TRIALS);
final int numberOfTrials = scanner.nextInt();
scanner.close();
printEmptyLine();
return numberOfTrials;
}

private void printEmptyLine() {
System.out.println();
}

}
31 changes: 31 additions & 0 deletions src/main/java/step2/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package step2.view;

import step2.domain.Car;
import step2.domain.Cars;

public class OutputView {
private static final String POSITION_OF_CAR = "-";

public void showResultTitle() {
System.out.println("실행 결과");
}

public void showResult(Cars cars) {
for (Car car : cars.getCars()) {
printCars(car);
}
printEmptyLine();
}

private void printCars(Car car) {
for (int i = 0; i < car.getPosition(); i++) {
System.out.print(POSITION_OF_CAR);
}
printEmptyLine();
}

private void printEmptyLine() {
System.out.println();
}

}
11 changes: 11 additions & 0 deletions src/test/java/step2/CarRaceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package step2;

import org.junit.jupiter.api.Test;

public class CarRaceTest {

@Test
void 입력된_값의_유효성검증이_유효하다() {
// TODO
}
}
43 changes: 43 additions & 0 deletions src/test/java/step2/CarTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package step2;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import step2.domain.Car;

import static org.assertj.core.api.Assertions.assertThat;

public class CarTest {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자동차 이동조건과 관련된 테스트가 없네요.


private Car car = new Car();

@Test
void 자동차가_생성된다() {
assertThat(car).isNotNull();
}

@Test
void 생성된_자동차의_시작포지션은_0이다() {
assertThat(car.getPosition()).isEqualTo(0);
}

@Test
void 입력된_숫자만큼_자동차가_생성된다() {
//TODO

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO에 앞으로 할 작업 목록을 작성해주는 것이 좋습니다.
IDE에서 TODO로 달린 주석 리스트를 확인하실 수 있습니다.
스크린샷 2019-06-19 오전 8 46 49

}

@Test
void 자동차는_랜덤숫자가_4이상인_경우만_이동한다() {
//TODO
}

@ParameterizedTest
@ValueSource(ints = {1, 2, 3, 4, 5})
void 자동차가_이동기준을_통과한_횟수만큼_이동한다(int numberOfMoves) {
final int aboveMoveCriterionNumber = 5;
for (int i = 0; i < numberOfMoves; i++) {
car.move(aboveMoveCriterionNumber);
}
assertThat(car.getPosition()).isEqualTo(numberOfMoves);
}
}