-
Notifications
You must be signed in to change notification settings - Fork 13
[3주차] 객체지향 코드 연습(방현우) #4
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
base: main
Are you sure you want to change the base?
Changes from all commits
fe78ba7
a0ded45
29b975b
a0ebe7e
fd71c36
8b6443f
79dd22d
6dcc583
72bdccb
d57b776
05489be
b60b7f7
bc8e2f3
f64b6ed
41720ef
94149ed
dabf12d
3470ab6
ec9dcbc
b37b905
529e242
f881f8f
209935b
53b9be5
389d8fa
e52178d
d0c80b0
89b9cab
f2a6a3b
f91d958
9317cc2
e0ed130
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
## 도메인 | ||
### 모델 | ||
- [X] RacingCar 클래스 | ||
- [X] name 길이 검증 메서드 | ||
- [X] name 존재 검증 메서드 | ||
- [X] name 공백 검증 메서드 | ||
- [X] position move 메서드 | ||
- [X] RacingCar을 리스트로 한 RacingCars 클래스 | ||
- [X] 이름 중복 검증 메서드 | ||
- [X] 이름 목록 Empty 검증 메서드 | ||
- [X] 레이스 참가 레이싱카 생성 팩토리 메서드 //이펙티브 자바 | ||
- [X] 게임을 담당할 Race 클래스 생성 | ||
- [X] 게임 시작 메서드 | ||
- [X] position 비교 메서드 | ||
- [X] 이곳에서 경기 결과 나오는게 맞다 판단하여 findResult, getWinner 메서드 생성 | ||
- [X] 게임 시도 숫자 검증할 TryNumber 클래스 | ||
|
||
|
||
## 컨트롤러 | ||
- [X] 컨트롤러(컨트롤러 인터페이스화) | ||
- | ||
## View | ||
- [X] view(인터페이스로 나누기 outView 재사용 위해) | ||
- [X] 출력 되는 것들은 전부 outView 로 | ||
- [X] 입력받는 것들은 전부 inputView 로 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,22 @@ | ||||||
package racingcar; | ||||||
|
||||||
import racingcar.controller.Controller; | ||||||
import racingcar.controller.RaceController; | ||||||
import racingcar.view.InputView; | ||||||
import racingcar.view.OutputView; | ||||||
|
||||||
public class AppConfig { | ||||||
|
||||||
public Controller controller() { | ||||||
return new RaceController(inputView(),outputView()); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
컨벤션! |
||||||
} | ||||||
|
||||||
private InputView inputView() { | ||||||
return new InputView(); | ||||||
} | ||||||
private OutputView outputView() { | ||||||
return new OutputView(); | ||||||
} | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
필요없는 줄바꿈 제거해주세요 |
||||||
|
||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
package racingcar; | ||
|
||
import racingcar.controller.Controller; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
// TODO: 프로그램 구현 | ||
AppConfig appConfig = new AppConfig(); | ||
|
||
Controller controller = appConfig.controller(); | ||
|
||
controller.execute(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package racingcar.controller; | ||
|
||
public interface Controller { | ||
void execute(); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,73 @@ | ||||||||||
package racingcar.controller; | ||||||||||
|
||||||||||
import racingcar.domain.model.*; | ||||||||||
import racingcar.domain.model.dto.FinalWinnerDTO; | ||||||||||
import racingcar.domain.model.dto.RoundResultDTO; | ||||||||||
import racingcar.global.ErrorMessage; | ||||||||||
import racingcar.view.InputView; | ||||||||||
import racingcar.view.OutputView; | ||||||||||
|
||||||||||
import java.util.Arrays; | ||||||||||
import java.util.List; | ||||||||||
import java.util.stream.Collectors; | ||||||||||
|
||||||||||
public class RaceController implements Controller { | ||||||||||
public static final int START_ROUND = 1; | ||||||||||
|
||||||||||
private final InputView inputView; | ||||||||||
private final OutputView outputView; | ||||||||||
|
||||||||||
public RaceController(InputView inputView, OutputView outputView) { | ||||||||||
this.inputView = inputView; | ||||||||||
this.outputView = outputView; | ||||||||||
} | ||||||||||
|
||||||||||
@Override | ||||||||||
public void execute() { | ||||||||||
RacingCars racingCars = inputName(); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메서드명을 적절히 수정해주면 좋을 것 같아요! |
||||||||||
Race race = raceProcess(racingCars); | ||||||||||
printResult(race); | ||||||||||
} | ||||||||||
|
||||||||||
private void printResult(Race race) { | ||||||||||
String finalResult = FinalWinnerDTO.from(race).getWinnersAsString(); | ||||||||||
outputView.printWinningResult(finalResult); | ||||||||||
} | ||||||||||
|
||||||||||
private Race raceProcess(RacingCars racingCars) { | ||||||||||
outputView.printTryNumberNotice(); | ||||||||||
TryNumber tryNumber = validateInputTryNumber(inputView.inputTryNumber()); | ||||||||||
Comment on lines
+38
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 입력을 위한 출력 메시지는 입력 객체 내부에서 진행하는 것은 어떤가요?
Comment on lines
+38
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 시도 횟수이므로
Suggested change
이 네이밍은 어떤가요? |
||||||||||
Race race = null; | ||||||||||
for (int i = START_ROUND; i <= tryNumber.getTryNumber(); i++) { | ||||||||||
race = Race.create(racingCars, tryNumber); | ||||||||||
outputView.printRoundResult(RoundResultDTO.from(race.startRace(),race)); | ||||||||||
} | ||||||||||
return race; | ||||||||||
} | ||||||||||
Comment on lines
+40
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 출력로직과 도메인 로직이 얽혀있는 것 같아요! Race를 끝마치고 출력하는 방식으로 바꿔보는 것은 어떤가요? |
||||||||||
|
||||||||||
private RacingCars inputName() { | ||||||||||
outputView.printInitialName(); | ||||||||||
return RacingCars.create(createRacingCars()); | ||||||||||
} | ||||||||||
|
||||||||||
|
||||||||||
private List<RacingCar> createRacingCars() { | ||||||||||
return Arrays.stream(inputView.inputName().split(",")) | ||||||||||
.map(String::trim) | ||||||||||
.map(RacingCar::create) | ||||||||||
.collect(Collectors.toList()); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. java 16버전에 새로 나온 |
||||||||||
} | ||||||||||
Comment on lines
+54
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CarName 컬렉션을 만드는 행위와 |
||||||||||
|
||||||||||
|
||||||||||
private TryNumber validateInputTryNumber(String tryNumber) { | ||||||||||
try { | ||||||||||
if (tryNumber.trim().isEmpty()) { | ||||||||||
throw new IllegalArgumentException(ErrorMessage.EMPTY_INPUT); | ||||||||||
} | ||||||||||
return TryNumber.from(Integer.parseInt(tryNumber)); | ||||||||||
} catch (NumberFormatException e) { | ||||||||||
throw new IllegalArgumentException(ErrorMessage.INVALID_NUMBER_FORMAT); | ||||||||||
} | ||||||||||
|
||||||||||
} | ||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,50 @@ | ||||||||||||||
package racingcar.domain.model; | ||||||||||||||
|
||||||||||||||
import racingcar.global.ErrorMessage; | ||||||||||||||
|
||||||||||||||
import java.util.List; | ||||||||||||||
import java.util.Map; | ||||||||||||||
import java.util.stream.Collectors; | ||||||||||||||
|
||||||||||||||
public class Race { | ||||||||||||||
|
||||||||||||||
private final RacingCars racingCars; | ||||||||||||||
private final TryNumber tryNumber; | ||||||||||||||
Comment on lines
+9
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 시도 횟수마다 인스턴스가 생성되는데, 전체적으로 관리되는 Race라는 네이밍은 조금 추상적인 것 같아요! |
||||||||||||||
|
||||||||||||||
private Race(RacingCars racingCars, TryNumber tryNumber) { | ||||||||||||||
this.racingCars = racingCars; | ||||||||||||||
this.tryNumber = tryNumber; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
public static Race create(RacingCars racingCars, TryNumber tryNumber) { | ||||||||||||||
return new Race(racingCars, tryNumber); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
public RacingCars startRace() { | ||||||||||||||
return RacingCars.create(racingCars.moveAll()); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moveAll에서 새로운 RacingCars를 생성한 뒤 반환하는 것은 어떤가요? |
||||||||||||||
} | ||||||||||||||
Comment on lines
+23
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 시작하는 것뿐만 아니라 계속해서 시도하고 있는 것이라면 try가 낫지 않을까요?
Suggested change
|
||||||||||||||
|
||||||||||||||
public Map<String, Integer> findResult() { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 일급컬렉션을 생성하여 반환하면 의미 전달이 더 잘될 것 같아요 |
||||||||||||||
return racingCars.getRacingCars().stream() | ||||||||||||||
.collect(Collectors.toMap( | ||||||||||||||
RacingCar::getName, | ||||||||||||||
RacingCar::getPosition | ||||||||||||||
)); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
public List<String> getWinners() { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 일급컬렉션으로 변경해도 좋을 것 같아요 |
||||||||||||||
int winningPosition = findWinningPosition(); | ||||||||||||||
return racingCars.getRacingCars().stream() | ||||||||||||||
.filter(car -> car.getPosition() == winningPosition) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. car 객체에게 메시지를 던질 수 있을 것 같아요 |
||||||||||||||
.map(RacingCar::getName) | ||||||||||||||
.toList(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
private int findWinningPosition() { | ||||||||||||||
return racingCars.getRacingCars().stream() | ||||||||||||||
.mapToInt(RacingCar::getPosition) | ||||||||||||||
.max() | ||||||||||||||
.orElseThrow(() -> new IllegalStateException(ErrorMessage.NO_CARS_TO_RACE)); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package racingcar.domain.model; | ||
|
||
import racingcar.global.ErrorMessage; | ||
|
||
import static camp.nextstep.edu.missionutils.Randoms.pickNumberInRange; | ||
|
||
public class RacingCar { | ||
public static final int MIN = 0; | ||
public static final int MAX = 9; | ||
public static final int MOVE_NUMBER = 4; | ||
public static int START_POSITION = 0; | ||
Comment on lines
+8
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. public으로 선언하신 이유가 있나요? |
||
|
||
private final String name; | ||
private int position = START_POSITION; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 추가된 요구사항에 외부에서 포지션을 지정해주고 싶다면 변경이 힘들것 같아요. |
||
|
||
private RacingCar(String name) { | ||
validateNameLength(name); | ||
validateNameEmpty(name); | ||
Comment on lines
+16
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Name과 관련된 검증이 이루어지고 있는데, CarName 객체를 새로 생성하는 것은 어떨까요? |
||
this.name = name; | ||
} | ||
|
||
public static RacingCar create(String name) { | ||
return new RacingCar(name); | ||
} | ||
|
||
private void validateNameLength(String name) { | ||
if (name.length() > 5) { | ||
throw new IllegalArgumentException(ErrorMessage.NAME_TOO_LONG); | ||
} | ||
} | ||
|
||
private void validateNameEmpty(String name) { | ||
if (name == null) { | ||
throw new IllegalArgumentException(ErrorMessage.NAME_MISSING); | ||
} | ||
} | ||
|
||
public void move() { | ||
if (pickNumberInRange(MIN, MAX) >= MOVE_NUMBER) { | ||
position++; | ||
} | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
|
||
public int getPosition() { | ||
return position; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package racingcar.domain.model; | ||
|
||
import racingcar.global.ErrorMessage; | ||
|
||
import java.util.List; | ||
|
||
public class RacingCars { | ||
private final List<RacingCar> racingCars; | ||
|
||
private RacingCars(List<RacingCar> racingCars) { | ||
validateNameListEmpty(racingCars); | ||
validateDuplicateName(racingCars); | ||
this.racingCars = List.copyOf(racingCars); | ||
} | ||
|
||
public static RacingCars create(List<RacingCar> userInput) { | ||
return new RacingCars(userInput); | ||
} | ||
|
||
public List<RacingCar> moveAll() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 컬렉션을 그대로 반환한다면 일급 컬렉션을 생성한 의미가 떨어지지 않을까요? |
||
racingCars.forEach(RacingCar::move); | ||
return racingCars; | ||
} | ||
|
||
|
||
private void validateDuplicateName(List<RacingCar> racingCars) { | ||
if (racingCars.size() != racingCars.stream().distinct().count()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이름이 같다고 같은 객체임을 구현해주지 않았는데, 제대로 동작하나요!? |
||
throw new IllegalArgumentException(ErrorMessage.DUPLICATE_NAME); | ||
} | ||
} | ||
|
||
private void validateNameListEmpty(List<RacingCar> racingCars) { | ||
if (racingCars.isEmpty()) { | ||
throw new IllegalArgumentException(ErrorMessage.EMPTY_NAME_LIST); | ||
} | ||
} | ||
|
||
|
||
public List<RacingCar> getRacingCars() { | ||
return racingCars; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,29 @@ | ||||||||||||||||
package racingcar.domain.model; | ||||||||||||||||
|
||||||||||||||||
import racingcar.global.ErrorMessage; | ||||||||||||||||
|
||||||||||||||||
public class TryNumber { | ||||||||||||||||
public static final int MIN = 0; | ||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
private final int tryNumber; | ||||||||||||||||
Comment on lines
+6
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
줄바꿈도 컨벤션! |
||||||||||||||||
|
||||||||||||||||
private TryNumber(int tryNumber) { | ||||||||||||||||
validateTryNumber(tryNumber); | ||||||||||||||||
this.tryNumber = tryNumber; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
public static TryNumber from(int tryNumber) { | ||||||||||||||||
return new TryNumber(tryNumber); | ||||||||||||||||
} | ||||||||||||||||
Comment on lines
+16
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다른 객체는 create인데, 이 객체는 from이네요! |
||||||||||||||||
|
||||||||||||||||
private void validateTryNumber(int tryNumber) { | ||||||||||||||||
if (tryNumber <= MIN) { | ||||||||||||||||
throw new IllegalArgumentException(ErrorMessage.INVALID_TRY_NUMBER); | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
public int getTryNumber() { | ||||||||||||||||
return tryNumber; | ||||||||||||||||
} | ||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package racingcar.domain.model.dto; | ||
|
||
import racingcar.domain.model.Race; | ||
|
||
|
||
public class FinalWinnerDTO { | ||
private final Race race; | ||
|
||
private FinalWinnerDTO(Race race) { | ||
this.race = race; | ||
} | ||
|
||
public static FinalWinnerDTO from(Race race) { | ||
return new FinalWinnerDTO(race); | ||
} | ||
|
||
public String getWinnersAsString() { | ||
return String.join(", ", race.getWinners()); | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package racingcar.domain.model.dto; | ||
|
||
import racingcar.domain.model.Race; | ||
import racingcar.domain.model.RacingCars; | ||
|
||
import java.util.Map; | ||
|
||
public class RoundResultDTO { | ||
private final RacingCars racingCars; | ||
private final Race race; | ||
|
||
private RoundResultDTO(RacingCars racingCars, Race race) { | ||
this.racingCars = racingCars; | ||
this.race = race; | ||
} | ||
|
||
|
||
public static RoundResultDTO from(RacingCars racingCars, Race race) { | ||
return new RoundResultDTO(racingCars, race); | ||
} | ||
|
||
|
||
public Map<String,Integer> getRacingCars() { | ||
return race.findResult(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package racingcar.global; | ||
|
||
public class ErrorMessage { | ||
public static final String EMPTY_INPUT = "빈 값이 들어오면 안됩니다."; | ||
public static final String INVALID_NUMBER_FORMAT = "정수만 입력 가능합니다."; | ||
|
||
public static final String NAME_TOO_LONG = "이름은 5자 이하여야 합니다."; | ||
public static final String NAME_MISSING = "이름이 존재하지 않습니다."; | ||
public static final String DUPLICATE_NAME = "중복된 이름이 존재합니다."; | ||
public static final String EMPTY_NAME_LIST = "이름 목록이 비어있습니다."; | ||
|
||
public static final String NO_CARS_TO_RACE = "경주할 자동차가 없습니다."; | ||
public static final String INVALID_TRY_NUMBER = "시도 숫자는 0보다 커야합니다."; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
객체간 의존성을 그림으로 그리면 어떤 관계를 가지고 있는지 쉽게 알 수 있을 것 같아요