Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
97202cd
docs: ReadMe를 작성하라
DevRunner21 Mar 14, 2022
1da6266
feat: 자동차 이름 생성 기능을 구현하라
DevRunner21 Mar 14, 2022
c502a69
feat: Try 생성 기능을 구현하라
DevRunner21 Mar 14, 2022
6b068d3
feat: RandomNumber 생성 로직을 구현하라
DevRunner21 Mar 14, 2022
f21aefc
feat: 자동차를 움직이는 기능을 구현하라
DevRunner21 Mar 14, 2022
57472e2
refactor: Car의 생성인자로 객체가 아닌 Literal 타입으로 수정하라
DevRunner21 Mar 14, 2022
6567a14
docs: ReadMe 내용을 수정하라
DevRunner21 Mar 14, 2022
6533332
feat: 모든 자동차를 이동시키는 기능을 구현하라
DevRunner21 Mar 14, 2022
aaf7f35
refactor: 시도 횟수 저장을 위해 만들었던 Try Class를 TryCount Class로 변경하라
DevRunner21 Mar 14, 2022
9687f38
fix: 잘못 표기된 상수명을 변경하라
DevRunner21 Mar 14, 2022
6221dff
feat: "시도 횟수" 만큼 자동차들을 움직이는 기능을 구현하라
DevRunner21 Mar 14, 2022
866f1bb
refactor: RandomNumber 생성 로직을 변경에 유연하게 재설계하라
DevRunner21 Mar 16, 2022
30f7917
refactor: 잘못된 상수 사용을 수정하라
DevRunner21 Mar 16, 2022
870ab11
fix: RandomNumber 범위값(MAX, MIN) 세팅 로직을 수정하라
DevRunner21 Mar 16, 2022
b923bec
refactor: 잘못 세팅된 접근제어자를 수정하라
DevRunner21 Mar 16, 2022
b9400bc
refactor: RandomNumber 로직을 FactoryMethod 패턴으로 변경하라
DevRunner21 Mar 17, 2022
2f80191
refactor: Car의 move 기능을 전략패턴으로 수정하라
DevRunner21 Mar 18, 2022
83f4dca
refactor: Car를 가변객체로 수정하고 Position을 불변객체로 수정하라
DevRunner21 Mar 18, 2022
139df34
test: MoveStrategy에 대한 테스트 코드를 작성하라
DevRunner21 Mar 18, 2022
3dcef78
test: DisplayName을 없애고 테스트 메서드 명을 한글로 변경하라
DevRunner21 Mar 18, 2022
626c531
refactor: TryCount를 제대로 캡슐화하라
DevRunner21 Mar 18, 2022
588c5da
refactor: 추상클래스 네이밍을 변경하라 ( NumberFactory -> AbstractNumberFactory )
DevRunner21 Mar 18, 2022
2ca4abb
refactor: TryCount에서 직접 Car를 move 하고 있던 역할을 Race에게 옮겨라
DevRunner21 Mar 24, 2022
bf114f9
refactor: final이 빠진 부분에 final을 기입하라
DevRunner21 Mar 24, 2022
a25c6a9
refactor: 생성자 중복코드에 대해서 this키워드를 이용해서 중복코드를 제거하라
DevRunner21 Mar 24, 2022
6455b38
refactor: AbstractNumber의 추상화 수준을 낮춰라
DevRunner21 Mar 24, 2022
8cb2640
refactor: 클래스 내의 상수를 static 상수로 변경하라
DevRunner21 Mar 24, 2022
38a82c8
refactor: 함수형인터페이스를 활용하여 Race, Cars, Car 단위테스트를 Strategy에서 독립적으로 수정하라
DevRunner21 Mar 24, 2022
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
46 changes: 29 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
## [NEXTSTEP 플레이그라운드의 미션 진행 과정](https://github.com/next-step/nextstep-docs/blob/master/playground/README.md)
# 자동차 경주 게임

---
## 학습 효과를 높이기 위해 추천하는 미션 진행 방법
## 규칙

---
1. 피드백 강의 전까지 미션 진행
> 피드백 강의 전까지 혼자 힘으로 미션 진행. 미션을 진행하면서 하나의 작업이 끝날 때 마다 add, commit
> 예를 들어 다음 숫자 야구 게임의 경우 0, 1, 2단계까지 구현을 완료한 후 push
- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용
- else 예약어를 쓰지 않는다
- 3항 연산자를 쓰지 않는다.
- 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라.
- **모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다.**
- **모든 원시 값과 문자열을 포장한다.**
- **일급 컬렉션을 쓴다.**
- **Getter를 쓰지 않는다.**

![mission baseball](https://raw.githubusercontent.com/next-step/nextstep-docs/master/playground/images/mission_baseball.png)
## 기능 요구사항

---
2. 피드백 앞 단계까지 미션 구현을 완료한 후 피드백 강의를 학습한다.
- 각 자동차에 이름을 부여할 수 있다. 자동차 이름은 5자를 초과할 수 없다.
- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
- 자동차 이름은 쉼표(,)를 기준으로 구분한다.
- 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우이다.
- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한명 이상일 수 있다.

---
3. Git 브랜치를 master 또는 main으로 변경한 후 피드백을 반영하기 위한 새로운 브랜치를 생성한 후 처음부터 다시 미션 구현을 도전한다.

```
git branch -a // 모든 로컬 브랜치 확인
git checkout master // 기본 브랜치가 master인 경우
git checkout main // 기본 브랜치가 main인 경우
## 구현 사항

git checkout -b 브랜치이름
ex) git checkout -b apply-feedback
```
---
- [ ] 자동차 이름들을 입력한다.
- [x] "자동차 이름"은 5자를 초과 할 수 없다.
- [ ] "시도 할 횟수"를 입력한다.
- [x] 시도 횟수는 음수 일 수 없다.
- [x] 경기를 시작한다.
- [x] "시도 횟수" 만큼 자동차들을 움직인다.
- [x] 모든 자동차를 움직인다.
- [x] 자동차를 움직인다.
- [x] 0 이상 9 이하의 랜덤 값을 받는다.
- [x] 4 이상일 경우 한 칸 전진한다.
- [ ] 우승자를 출력한다.
17 changes: 17 additions & 0 deletions src/main/java/AbstractNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
public abstract class AbstractNumber {
Copy link
Member

Choose a reason for hiding this comment

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

해당 클래스가 존재해야 하는 이유는 무엇일까요??
어떤 점을 염두하고 만드신건지 궁금해요!!!!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

이 부분은 move()의 조건이 되는 숫자의 유형이 바뀌는 걸 염두했습니다.
move를 위해 주어지는 수가 0~9까지의 난수 일수도 있고, 짝수일 수도 있고, 홀수일 수도 있죠.

그래서 일단 숫자 라는 걸 추상객체로 만들고 ( AbstractNumber )
그 하위 클래스로는 조건이 부여된 숫자를 만드는 걸 생각했습니다.

move의 조건이 "0~9까지의 난수" 에서 "짝수"라고 바뀌어도 변경이 없게 말이죠.


Copy link
Member

Choose a reason for hiding this comment

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

추상화 수준을 낮춘다면 조금 더 이해하기 쉬운 코드가 될것 같아요.

private final int number;

public AbstractNumber(int number) {
this.number = number;
}

public boolean isMoreThan(int comparisonNumber) {
return comparisonNumber <= number;
}

public boolean isLessThan(int comparisonNumber) {
return comparisonNumber >= number;
}

}
5 changes: 5 additions & 0 deletions src/main/java/AbstractNumberFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public abstract class AbstractNumberFactory {

abstract AbstractNumber produce();

}
48 changes: 48 additions & 0 deletions src/main/java/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import java.util.Objects;

public class Car {

private final Name name;
private Position position;
private final MoveStrategy strategy;

Copy link
Member

Choose a reason for hiding this comment

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

Car 객체가 불변이기 때문에 Position 객체는 불변성을 확보하지 못한것 같아요.
저는 Car 보단 Position 객체의 불변성을 가져오고, 인스턴스를 재활용 할것 같아요.
Car객체가 불변인 상태로 필드가 계속해서 늘어난다면 불변성을 지키면서 확장하기도 매우 어려울것 같아요 😊

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

말씀해주신 내용에 대해서 제가 이해한 내용을 말씀드려보자면

정리

현재 코드 상황을 정리해 보자면 Car는 불변객체이고 Position은 불변성을 확보하지 못한 상태입니다.
그 이유는 Position의 값이 전진 할 때 마다 변경되어야 하는데,
결국엔 값의 변경이 일어나다 보니 Car의 Position인스턴스를 교체하던지, Position의 필드 값을 바꿔야 하게되죠.
즉, 무조건 둘 중 하나는 불변성을 잃어야하는 상황입니다.

여기서 저는 Position 값의 변경은 Position 본인이 책임져야 할 부분이라고 생각해서
Position의 불변성을 없애고 내부에서 상태를 변경 시킬 수 있도록 했습니다.
이렇게 했을 때, 객체간의 결합도를 낮출 수 있다고 생각했죠.

하지만 재원님의 말씀을 듣고보니
만약 이렇게 할 경우 Name을 변경 해야 할 경우 Name 객체의 불변성을 없앨 것이고,
다른 필드들이 추가되고 그 필드의 내용을 수정해야 할 경우 전부 불변성을 잃은 객체로 만들게 되겠군요.

즉 수정이 필요한 필드마다 불변성을 없애게 될 테니, 확장에 있어서 지속적인 불변성을 지키기가 어렵겠군요!
Car객체가 불변인 상태로 필드가 계속해서 늘어난다면 불변성을 지키면서 확장하기도 매우 어려울 것 같아요 😊

그래서 어차피 완전한 불변성을 지키기 어려운 경우라면
여러 개의 가변 객체가 생기는 것 보다는 Car 객체 하나를 가변객체로 두는 것이 확장에 있어서
불변성을 지키기가 더 수월하다! 라고 이해했는데,
제가 이해한 내용이 맞나요?

질문


그렇다면 Car를 가변객체로 만들 경우 아래와 같이 Position의 인스턴스를 Car에서 만들어서 갈아끼우게 될텐데

public void moveToOneStep(){
 this.position = new Position(1);
}

이때, Position의 내부구조가 Car에 노출되다보니 결국 결합도가 올라간다는 단점이 있을 것 같습니다.
결국 불변성 vs 객체간의 결합도 중 트레이드 오프를 고민해야 하는데,
재원님께서는 불변성을 더 중요하게 생각하신 이유가 있을까요? @darkant99
(
재원님의 피드백을 보고 저도 불변성을 지키는게 더 나을 것 같은게
객체간의 결합도 문제는 Runtime에서 문제가 생기지는 않지만
불변성에 대한 부분은 동시성 이슈로 인해 Runtime에서 연쇄적인 이슈가 발생할 가능성이 높아서
둘중 하나를 고르라고 하면 불변성을 지키는게 운영상 더 이득일거라고 생각합니다. ㅎㅎ
)

Copy link
Member

Choose a reason for hiding this comment

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

move 메서드에서도 동시성 이슈가 발생할거라고 판단되는데 Car는 이미 가변 객체 일수도 있어요🤔
Car를 Entity 와 비유 해보면 어떨까요?
Car가 자신의 상태에 대해서 결합도를 낮춰야 할까요? 저는 아니라고 생각해요.
불변성과 결합도 중 트레이드 오프를 고려하는것보단
아래처럼 만들어 불변성과 응집도를 챙길 수 있다고 생각해요 😇

public void moveToOneStep() {
this.position = position.moveOneStep();
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Car를 Entity 와 비유 해보면 어떨까요?
Car가 자신의 상태에 대해서 결합도를 낮춰야 할까요?

오! 이렇게 보니 딱 이해가 됩니다.
자신의 상태와 결합도를 낮출 필요는 없겠군요!

그냥 생성자를 가져다 쓰는 것만 생각했는데
아래와 같이 응집도까지 챙길수 있다니~ 크~~ 👍👍👍👍

public void moveToOneStep() {
    this.position = position.moveOneStep();
}

Copy link
Member

Choose a reason for hiding this comment

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

private final Name name;
private Position position;
private final MoveStrategy strategy;

가변 객체라도 불변을 지향하는게 좋아보여요 😃

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Car를 가변객체로 바꿨다고 해도
불변으로 둬도 될 필드는 불변으로 두는게 더 좋겠군요!
피드백 감사합니다! ㅎㅎ

public Car(String name, int position, MoveStrategy strategy) {
this(name, strategy);
this.position = new Position(position);
}

public Car(String name, MoveStrategy strategy) {
validateMoveStrategy(strategy);
this.name = new Name(name);
this.position = new Position();
this.strategy = strategy;
}

Copy link
Member

Choose a reason for hiding this comment

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

메인 생성자를 하나로 두고, 나머지 생성자에서는 this 키워드로 전달하는게 어떨까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

중복되는 코드가 있으니 생성자를 하나로 통일하라는 말씀으로 이해되는데

메인 생성자를 하나로 두고, 나머지 생성자에서는 this 키워드로 전달

이 말이 잘 이해가 안됩니다 ㅜㅜ
혹시 좀 더 설명 부탁드려도 될까요? ㅜㅜ
@darkant99

Copy link
Member

Choose a reason for hiding this comment

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

실제 생성자는 하나로 두고 this 키워드를 사용해서 생성자를 오버로딩 하면 좋을것 같아요 👍

private void validateMoveStrategy(MoveStrategy strategy) {
if (Objects.isNull(strategy)) {
throw new IllegalArgumentException("MoveStrategy must be not null");
}
}

public void move() {
this.position = strategy.move(this.position);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Car car = (Car) o;
return Objects.equals(name, car.name) && Objects.equals(position, car.position);
}

@Override
public int hashCode() {
return Objects.hash(name, position);
}

}
44 changes: 44 additions & 0 deletions src/main/java/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class Cars {

private final List<Car> cars = new ArrayList<>();

public Cars(List<Car> cars) {
validate(cars);
this.cars.addAll(cars);
Copy link
Member

Choose a reason for hiding this comment

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

cars를 직접 대입하지 않고 요소들의 참조를 각각 추가 해주셨네요 이유가 있을까요? 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

이 부분의 경우 원래 생성자의 인자로 List<Car>가 아니라 Car의 이름들을 담은 List<String> names 를 받다가
나중에 수정했는데,
인자값만 바꾸고 대입로직은 수정을 안했었네요 ㅜㅜ

피드백 감사합니다!!
코드 변경시 꼼꼼히 확인해야겠군여 ㅜㅜ

}

private void validate(List<Car> cars) {
if (Objects.isNull(cars)) {
throw new IllegalArgumentException("cars는 Null일 수 없습니다.");
}
if (cars.isEmpty()) {
throw new IllegalArgumentException("cars는 Enpty 일 수 없습니다.");
Comment on lines +15 to +19
Copy link
Member

Choose a reason for hiding this comment

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

넘어오는 데이터에 대한 방어로직일까요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

네! 맞습니다!
이번에 생성자 마다 되도록이면 validationCheck를 확실하게 하고 싶어서 ㅎㅎ

}
}

public void move() {
cars.forEach(Car::move);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Cars cars1 = (Cars) o;
return Objects.equals(cars, cars1.cars);
}

@Override
public int hashCode() {
return Objects.hash(cars);
}

}
19 changes: 19 additions & 0 deletions src/main/java/MoveByRandomNumberStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
public class MoveByRandomNumberStrategy implements MoveStrategy{

private final int MOVABLE_CAR_MIN_NUMBER = 4;
Copy link
Member

Choose a reason for hiding this comment

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

static가 안붙었어요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

이 부분의 경우 해당 클래스 내부에서만 사용하는걸 의도해서 static을 붙이지 않았습니다.
중복되는 상수는 나중에 별도 클래스로 모을 계획이었죠. Constants.class 에 상수를 다 모아놓는 식으로 말이죠 ㅋㅋ

하지만 토비스트링 5장 347페이지를 보니
상수의 의미를 명확하게 전달 할 수 있는 Class에 static 상수로 넣어놓으니
테스트 코드에서까지 사용하는걸 보고서
클래스 마다 있는 상수를 static으로 가지고 있는게 낫겠다는 생각이 들었습니다. ㅋㅋ

이 부분은 수정해서 다시 올리겠습니다!
피드백 감사합니다!

Copy link
Member

Choose a reason for hiding this comment

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

static을 붙여도 private로 지정되있으면 클래스 내부에서만 사용 가능해요!

private final AbstractNumberFactory factory;

public MoveByRandomNumberStrategy(AbstractNumberFactory factory) {
this.factory = factory;
}

@Override
public Position move(Position position) {
AbstractNumber randomNumber = factory.produce();
if (randomNumber.isMoreThan(MOVABLE_CAR_MIN_NUMBER)) {
return position.moveOneStep();
}
return position;
}

}
3 changes: 3 additions & 0 deletions src/main/java/MoveStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public interface MoveStrategy {
Position move(Position position);
}
38 changes: 38 additions & 0 deletions src/main/java/Name.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import java.util.Objects;

public class Name {

private final int MAX_NAME_LENGTH = 5;
private final String NAME_LENGTH_OVER_MESSAGE = "자동차 이름은 5자를 초과할 수 없다.";

private final String name;

public Name(String name) {
validate(name);
this.name = name;
}

private void validate(String name) {
if (Objects.isNull(name) || name.length() > MAX_NAME_LENGTH) {
throw new IllegalArgumentException(NAME_LENGTH_OVER_MESSAGE);
}
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Name name1 = (Name) o;
return Objects.equals(name, name1.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}

}
45 changes: 45 additions & 0 deletions src/main/java/Position.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import java.util.Objects;

public class Position {

private final int ZERO = 0;
Copy link
Member

Choose a reason for hiding this comment

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

static으로 선언하지 않은 이유는 왜일까요?
다른 부분에서는 static으로 선언하신 것 같아서요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

저 변수를 해당 인스턴스 안에서만 사용하려고 static을 쓰지 않았습니다.
다른부분에 static이 들어간건 그 부분은 제가 실수로 고치지 않은 부분이었죠.. ㅎㅎ

근대 토비스프링 5장을 읽어보니 static 상수로 정의해놓고
테스트에서 그 상수를 사용하면 더 가독성이 좋더라구요!

그래서 테스트에서 사용할 상수의 경우 static 상수로 바꿀 생각입니다! ㅎㅎ


private final int step;

public Position() {
this.step = ZERO;
}

public Position(int step) {
validate(step);
this.step = step;
}

private void validate(int step) {
if (step < ZERO) {
throw new IllegalArgumentException("step에 음수를 입력할 수 없습니다.");
}
}

public Position moveOneStep() {
return new Position(step + 1);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Position position1 = (Position) o;
return step == position1.step;
}

@Override
public int hashCode() {
return Objects.hash(ZERO, step);
}

}
19 changes: 19 additions & 0 deletions src/main/java/Race.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
public class Race {

private TryCount tryCount;

private final Cars cars;

public Race(int tryCount, Cars cars) {
this.tryCount = new TryCount(tryCount);
Copy link
Member

Choose a reason for hiding this comment

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

tryCount를 받아서 Race가 생성되는데, 어디서 쓰이는 걸까요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

이 TryCount는 start()에서 활용됩니다.

요구사항이 입력한 "시도 횟수" 만큼 자동차를 전진시켜야 하는데
그를 구현하기 위해서는 반복분을 tryCount 만큼 돌려야 합니다.

하지만 이번 프로젝트에서는 getter를 사용하지 않다 보니
TryCount의 내부 값을 알 방법이 없었고 그래서 아래와 같이
TryCount 객체에게 Message를 보내면서 반복문을 돌려야 했습니다.

  while (tryCount.isOverThan(currentTryCount)){
      this.cars.move(factory);
      currentTryCount++;
  }

this.cars = cars;
}

public void start() {
while (!this.tryCount.isComplete()) {
cars.move();
Copy link
Member

Choose a reason for hiding this comment

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

부정보단 긍정이 더 잘 읽힌다고 합니다 😎
한번 시도 해보시면 재미있을것 같아요.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

아! 예전에 피드백 주셨던 내용이군요!
isNotComplete() 같은 형태가 확실히 술술 읽히겠군요!
수정하겠습니다!

this.tryCount = tryCount.getNextTryCount();
}
}

}
23 changes: 23 additions & 0 deletions src/main/java/RangeableRandomNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
public class RangeableRandomNumber extends AbstractNumber {

Copy link
Member

Choose a reason for hiding this comment

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

테스트 코드에서만 사용하고 있는 클래스인데, 테스트 패키지로 옮겨보면 어떨까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

사실 Input, Output을 안만든상태라 그렇습니다.. ㅎㅎ
원래로직대로면 메인 비즈니스 로직에서 사용될 클래스입니다 ㅎㅎ

private static final int MIN_RANDOM_NUMBER = 0;
private static final int MAX_RANDOM_NUMBER = 9;

private final int max;

private final int min;

public RangeableRandomNumber(int number) {
super(number);
this.max = MAX_RANDOM_NUMBER;
this.min = MIN_RANDOM_NUMBER;
validate(number);
}

Copy link
Member

Choose a reason for hiding this comment

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

public RangeableRandomNumber(int number) {
    this(number, DEFAULT_MAX_RANDOM_NUMBER, DEFAULT_MIN_RANDOM_NUMBER);
}

😇

private void validate(int number) {
if (number < min || number > max) {
throw new IllegalArgumentException("RangeableRandomNumber는 " + min + " 보다 크고 " + max + "보다 작아야 합니다.");
}
}

}
18 changes: 18 additions & 0 deletions src/main/java/RangeableRandomNumberFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import java.util.Random;

public class RangeableRandomNumberFactory extends AbstractNumberFactory {

public final int MAX_RANDOM_NUMBER = 9;

private final Random random;

public RangeableRandomNumberFactory() {
random = new Random();
}

@Override
public AbstractNumber produce() {
return new RangeableRandomNumber(random.nextInt(MAX_RANDOM_NUMBER));
}

}
Loading