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

Step5 - 리펙토링 #6073

Merged
merged 7 commits 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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,11 @@
* 우승자는 차량 이름으로 표시한다.
* ResultView에서 우승자 목록을 출력한다.
* 우승자가 여러명일 경우 쉼표(,)로 구분하여 표시한다.

### Step5
* 아래 3가지 개발 원칙을 적용해본다
* 모든 원시값과 문자열을 포장한다
* 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
* 한 줄에 점을 하나만 찍는다
* 일급 콜렉션을 쓴다
* 도메인 객체를 테스트가 가능하도록 수정
42 changes: 42 additions & 0 deletions src/main/java/race/CarList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package race;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class CarList {
private final List<RacingCar> cars;

public CarList() {
this(new ArrayList<>());
}

public CarList(List<RacingCar> cars) {
this.cars = cars;
}

public void add(RacingCar car) {
cars.add(car);
}

public void moveWithRandom(Random random) {
for (RacingCar car : cars) {
car.moveWithSeed(random.nextInt());
}
}

public List<RacingCar> getList() {
return cars;
}

public List<RacingCar> getWinners() {
cars.sort(Collections.reverseOrder());
RacingCar winner = cars.get(0);

return cars.stream()
.filter(car -> car.compareTo(winner) == 0)
.collect(Collectors.toList());
}
}
15 changes: 15 additions & 0 deletions src/main/java/race/CarName.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package race;

public class CarName {
private final String name;

public CarName(String name) {
this.name = name;
}

@Override
public String toString() {
return name;
}

}
8 changes: 0 additions & 8 deletions src/main/java/race/DefaultPositionPrinter.java

This file was deleted.

12 changes: 0 additions & 12 deletions src/main/java/race/DefaultRandomNumberGenerator.java

This file was deleted.

14 changes: 0 additions & 14 deletions src/main/java/race/FixedNumberGenerator.java

This file was deleted.

42 changes: 42 additions & 0 deletions src/main/java/race/Position.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package race;

import java.util.Objects;

public class Position implements Comparable<Position> {
private int value;

public Position() {
this(0);
}

public Position(int value) {
this.value = value;
}

public Position move() {
this.value++;
return this;
}

public int getValue() {
return this.value;
}

@Override
public int compareTo(Position o) {
return Integer.compare(this.value, o.value);
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Position position = (Position) obj;
return value == position.value;
}

@Override
public int hashCode() {
return Objects.hash(value);
}
}
5 changes: 0 additions & 5 deletions src/main/java/race/PositionPrinter.java

This file was deleted.

43 changes: 20 additions & 23 deletions src/main/java/race/RacingCar.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,44 @@

public class RacingCar implements Comparable<RacingCar> {
private static final int MAX_NAME_LENGTH = 5;
private final String name;
private int position;
private final RandomNumberGenerator randomNumberGenerator;
private final PositionPrinter positionPrinter;
private static final int MOVE_CRITERIA = 4;
private final CarName name;
private final Position position;

private RacingCar(String name, RandomNumberGenerator randomNumberGenerator, PositionPrinter positionPrinter) {
this.name = name;
this.randomNumberGenerator = randomNumberGenerator;
this.positionPrinter = positionPrinter;
public RacingCar(String name) {
this(name, 0);
}

@Override
public int compareTo(RacingCar other) {
return Integer.compare(this.position, other.position);
public RacingCar(String name, int position) {
this.name = new CarName(name);
this.position = new Position(position);
}

public static boolean validateName(String carName) {
return !carName.isEmpty() && carName.length() <= MAX_NAME_LENGTH;
}

private boolean shouldMove(int num) {
return num >= 4;
return num >= MOVE_CRITERIA;
}

public int move() {
int randomValue = randomNumberGenerator.generate();
if (shouldMove(randomValue)) {
position++;
public Position moveWithSeed(int seed) {
if (shouldMove(seed)) {
return this.position.move();
}
return position;
return this.position;
}

public void printPosition() {
positionPrinter.printPosition(name, position);
public CarName getName() {
return this.name;
}

static RacingCar create(String racingName, RandomNumberGenerator randomNumberGenerator, PositionPrinter positionPrinter) {
return new RacingCar(racingName, randomNumberGenerator, positionPrinter);
public Position getPosition() {
return this.position;
}

public String getName() {
return name;
@Override
public int compareTo(RacingCar o) {
return this.position.compareTo(o.position);
}
}
22 changes: 0 additions & 22 deletions src/main/java/race/RacingCarFactory.java

This file was deleted.

49 changes: 11 additions & 38 deletions src/main/java/race/RacingTrack.java
Original file line number Diff line number Diff line change
@@ -1,63 +1,43 @@
package race;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class RacingTrack {
private final int maxCarCount;
private final int maxAttemptCount;
private final List<RacingCar> cars;
private final TrackCondition trackCondition;
private final CarList cars;

public RacingTrack(int maxCarCount, int maxAttemptCount) {
this.maxCarCount = maxCarCount;
this.maxAttemptCount = maxAttemptCount;
this.cars = new ArrayList<>();
this.trackCondition = new TrackCondition(maxCarCount, maxAttemptCount);
this.cars = new CarList();
}

public void startRace(String[] carNames, int numOfAttempts) {
setupCars(carNames);

ResultView.printRaceStartMessage();
for (int i = 0; i < numOfAttempts; i++) {
moveAndShowCars();
ResultView.printRaceStatus(cars);
}
}

// getWinners() 메서드 테스틀 위하여 추가한 생성자
public void startRace(List<RacingCar> cars, int numOfAttempts) {
this.cars.addAll(cars);

ResultView.printRaceStartMessage();
for (int i = 0; i < numOfAttempts; i++) {
moveAndShowCars();
cars.moveWithRandom(new Random());
ResultView.printRaceStatus(cars);
}
}

private void setupCars(String[] carNames) {
for (String name : carNames) {
cars.add(RacingCarFactory.create(name, ResultView.createPositionPrinter()));
}
}

private void moveAndShowCars() {
for (RacingCar car : cars) {
car.move();
cars.add(new RacingCar(name));
}
}

public boolean validateCarCount(int num) {
return num >= 1 && num <= this.maxCarCount;
return this.trackCondition.validateCarCount(num);
}

public boolean validateAttemptCount(int num) {
return num >= 1 && num <= this.maxAttemptCount;
return this.trackCondition.validateAttemptCount(num);
}

public boolean validateCarNames(String[] names) {
if (names.length < 1 || names.length > this.maxCarCount) {
if (!this.trackCondition.validateCarCount(names.length)) {
return false;
}
for (String name : names) {
Expand All @@ -67,13 +47,6 @@ public boolean validateCarNames(String[] names) {
}

public List<RacingCar> getWinners() {
cars.sort(Collections.reverseOrder());
List<RacingCar> winners = new ArrayList<>();
winners.add(cars.get(0));

for (int i = 1; i < cars.size(); i++) {
if (cars.get(i).compareTo(cars.get(0)) == 0) winners.add(cars.get(i));
}
return winners;
return this.cars.getWinners();
}
}
5 changes: 0 additions & 5 deletions src/main/java/race/RandomNumberGenerator.java

This file was deleted.

17 changes: 4 additions & 13 deletions src/main/java/race/ResultView.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,21 @@
import java.util.List;

public class ResultView {
public static PositionPrinter createPositionPrinter() {
return new PositionPrinter() {
@Override
public void printPosition(String carName, int position) {
System.out.println(String.format("%-5s", carName) + " : " + "-".repeat(position));
}
};
}

public static void printRaceStartMessage() {
System.out.println("\n### Racing Start!!! ###\n");
}

public static void printRaceStatus(List<RacingCar> cars) {
for (RacingCar car : cars) {
car.printPosition();
public static void printRaceStatus(CarList cars) {
for (RacingCar car : cars.getList()) {
System.out.println(String.format("%-5s", car.getName().toString()) + " : " + "-".repeat(car.getPosition().getValue()));
}
System.out.println();
}

public static void printRaceWinners(List<RacingCar> cars) {
String[] winners = new String[cars.size()];
for (RacingCar car : cars) {
winners[cars.indexOf(car)] = car.getName();
winners[cars.indexOf(car)] = car.getName().toString();
}
System.out.println(String.join(", ", winners) + "가 최종 우승했습니다.");
}
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/race/TrackCondition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package race;

public class TrackCondition {
private final int maxCarCount;
private final int maxAttemptCount;

public TrackCondition(int maxCarCount, int maxAttemptCount) {
this.maxCarCount = maxCarCount;
this.maxAttemptCount = maxAttemptCount;
}

public boolean validateCarCount(int num) {
return num >= 1 && num <= this.maxCarCount;
}

public boolean validateAttemptCount(int num) {
return num >= 1 && num <= this.maxAttemptCount;
}
}
Loading