Skip to content
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

자동차 경주 - 5단계 #6083

Merged
merged 1 commit into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
51 changes: 0 additions & 51 deletions src/main/java/racingcar/Cars.java

This file was deleted.

2 changes: 2 additions & 0 deletions src/main/java/racingcar/RaceController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package racingcar;

import racingcar.view.InputView;

public class RaceController {

public void runRace() {
Expand Down
17 changes: 15 additions & 2 deletions src/main/java/racingcar/RaceService.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
package racingcar;

import java.util.List;
import java.util.stream.Stream;

import racingcar.domain.Cars;
import racingcar.domain.MovingStrategy;
import racingcar.domain.Race;
import racingcar.domain.RaceResult;
import racingcar.domain.RandomMovingStrategy;
import racingcar.view.OutputView;

public class RaceService {
private final Race race;
private final Cars cars;

public RaceService(String carInput, int roundInput) {
List<String> names = Stream.of(carInput.split(","))
Copy link

Choose a reason for hiding this comment

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

아주 소소한 의견이긴 한데, InputView에서 이 역할까지 하는건 어떨까 생각이 들었습니다 😄
사용자로부터 문자값을 입력 받고 그걸 처리한 결과를 전달하는 역할을 부여하면
좀 더 생성자 부분도 정리 될 것 같습니다 😄

public RaceService(List<String> names, int roundInput) {
// ...
}

개선까지는 아니고 정리 차원에서 이런 의견도 있구나 정도만 생각해주시면 될 것 같습니다 🙇

.map(String::trim)
.toList();
this.race = new Race(roundInput);
this.cars = new Cars(carInput);
this.cars = new Cars(names);
}

public void runRace() {
OutputView.printResultMessage();
while (race.hasRemainRound()) {
runOneRound();
}
OutputView.printWinner(cars.determineWinner());
OutputView.printWinner(RaceResult.determineWinner(cars.getCarsNameAndLocation()));
}

private void runOneRound() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package racingcar;
package racingcar.domain;
Copy link

Choose a reason for hiding this comment

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

정리 잘 해주셨네요 👍


public class Car {
private static final int MAX_CAR_NAME_LENGTH = 5;
private final String name;
private int location;

Expand All @@ -14,7 +15,7 @@ private void validateName(String name) {
if (name == null || name.isBlank()) {
throw new RuntimeException("자동차 이름은 공백일 수 없습니다.");
}
if (name.length() > 5) {
if (name.length() > MAX_CAR_NAME_LENGTH) {
Copy link

Choose a reason for hiding this comment

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

요청사항 반영 💯

throw new RuntimeException("자동차 이름은 1자 이상 5자 이하만 가능합니다.");
}
}
Expand All @@ -25,10 +26,6 @@ public void go(MovingStrategy movingStrategy) {
}
}

public boolean isSameLocation(int compareLocation) {
return compareLocation == location;
}

public int getLocation() {
return location;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package racingcar;
package racingcar.domain;

public record CarInfo(
String name,
Expand All @@ -10,4 +10,8 @@ public record CarInfo(
car.getLocation()
);
}

public boolean isSameLocation(int compareLocation) {
return compareLocation == location;
}
}
39 changes: 39 additions & 0 deletions src/main/java/racingcar/domain/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package racingcar.domain;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Cars {
private final List<Car> cars;

public Cars(List<String> names) {
validateDuplicateName(names);
List<Car> tempCars = new ArrayList<>();
for (String name : names) {
tempCars.add(new Car(name));
}
this.cars = tempCars;
Copy link

Choose a reason for hiding this comment

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

이 부분은 stream으로 간결하게 해볼 수 있을 것 같습니다 😄

// 16이전 
this.cars = names.stream()
		.map(Car::new)
		.collect(Collectors.toList());
// 16이후 
this.cars = names.stream()
		.map(Car::new)
		.toList();

}

private void validateDuplicateName(List<String> names) {
Set<String> uniqueNames = new HashSet<>(names);
if (uniqueNames.size() != names.size()) {
throw new RuntimeException("중복된 자동차 이름이 존재합니다.");
}
}

public void moveCars(MovingStrategy movingStrategy) {
for (Car car : cars) {
car.go(movingStrategy);
}
}

public List<CarInfo> getCarsNameAndLocation() {
return cars.stream()
.map(CarInfo::new)
.toList();
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package racingcar;
package racingcar.domain;

public interface MovingStrategy {
boolean canGo();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package racingcar;
package racingcar.domain;

public class Race {
private int remainingRounds;
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/racingcar/domain/RaceResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package racingcar.domain;

import java.util.List;

public class RaceResult {
Copy link

Choose a reason for hiding this comment

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

유틸도 좋은데 아예 List<CarInfo>를 관리하는 객체여도 나쁘지 않을 것 같습니다.
경기 결과를 담당하고 그에 따른 비즈니스 요건을 처리하는 역할을 담당하면 될 것 같네요 😄
다만 CarInfo를 상속받아 처리하는 다양한 Info들이 존재한다면 유틸 구조가 적당할 것 같습니다.

private RaceResult() {
throw new UnsupportedOperationException("유틸 클래스의 인스턴스를 생성할 수 없습니다.");
}

public static int findMaxLocation(List<CarInfo> cars) {
return cars.stream()
.mapToInt(CarInfo::location)
.max()
.orElseThrow(() -> new RuntimeException("자동차가 존재하지 않습니다."));
}

public static List<String> determineWinner(List<CarInfo> cars) {
int maxLocation = findMaxLocation(cars);
return cars.stream()
.filter(car -> car.isSameLocation(maxLocation))
.map(CarInfo::name)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package racingcar;
package racingcar.domain;

public class RandomMovingStrategy implements MovingStrategy {
private static final int MIN_MOVE_VALUE = 4;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package racingcar;
package racingcar.domain;

import java.util.Random;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package racingcar;
package racingcar.view;

import java.util.InputMismatchException;
import java.util.NoSuchElementException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package racingcar;
package racingcar.view;

import java.util.List;

Expand Down
39 changes: 39 additions & 0 deletions src/test/java/racingcar/CarInfoTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package racingcar;

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import racingcar.domain.CarInfo;

class CarInfoTest {
@Test
@DisplayName("거리가 동일하면 true를 반환한다.")
void isSameLocationTest_sameLocation() {
// given
int location = 4;
CarInfo carInfo = new CarInfo("pobi", location);

// when
boolean result = carInfo.isSameLocation(location);

// then
assertThat(result).isTrue();
}

@Test
@DisplayName("거리가 동일하지 않으면 false를 반환한다.")
void isSameLocationTest_differentLocation() {
// given
int location = 4;
CarInfo carInfo = new CarInfo("pobi", location);

// when
boolean result = carInfo.isSameLocation(location + 1);

// then
assertThat(result).isFalse();
}

}
21 changes: 2 additions & 19 deletions src/test/java/racingcar/CarTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;

import racingcar.domain.Car;

class CarTest {

@ParameterizedTest(name = "invalidName : {0}")
Expand Down Expand Up @@ -67,22 +68,4 @@ void goTest_stop() {
assertThat(car.getLocation()).isEqualTo(0);
}

@ParameterizedTest(name = "거리: {0}, 기대값: {1}")
@CsvSource({
"0, true",
"1, false"
})
@DisplayName("거리가 동일하면 true를 반환하고, 그렇지 않으면 false를 반환한다.")
void isSameLocationTest(int location, boolean expected) {
// given
Car car = new Car("tdd");

// when
boolean result = car.isSameLocation(location);

// then
assertThat(result).isEqualTo(expected);

}

}
Loading