-
Notifications
You must be signed in to change notification settings - Fork 252
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
[2단계 - 사다리 생성] 제이미(임정수) 미션 제출합니다. #201
Changes from 25 commits
0faa657
c337052
f417b0d
00aac30
acfe36e
82f126d
da00181
1f79bc4
1043538
85d183c
1b76f30
90bd727
6df7c53
5203156
c94305b
de78b60
0d3c367
1107fff
3d21b32
93a8476
765f14c
c0be9a4
f1ddbef
7148ab8
cf546ca
cf0409e
a6065ca
2eb1d2a
1a15d38
3cf3a5b
615707c
4ba26ca
90eb49c
81551b1
313e459
facbee6
4caaff5
32cf4e8
0815728
5281476
0a4a092
6a8768f
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 |
---|---|---|
|
@@ -4,13 +4,14 @@ | |
|
||
## 📚 도메인 모델 네이밍 사전 | ||
|
||
| 한글명 | 영문명 | 설명 | | ||
|-------|--------------|---------------------| | ||
| 참가자 | Participants | 사다리 게임에 참가하는 사람들을 지칭 | | ||
| 사람 | Person | 사람을 지칭 | | ||
| 맵 | Map | 맵 정보 지칭 | | ||
| 사다리 | Ladder | 사다리 지칭 | | ||
| 라인 | Line | 사다리의 한줄을 지칭 | | ||
| 한글명 | 영문명 | 설명 | | ||
|-----|--------------|----------------------| | ||
| 참가자 | Participants | 사다리 게임에 참가하는 사람들을 지칭 | | ||
| 사람 | Person | 사람을 지칭 | | ||
| 맵 | Map | 맵 정보 지칭 | | ||
| 사다리 | Ladder | 사다리 지칭 | | ||
| 라인 | Line | 사다리의 한줄을 지칭 | | ||
| 결과 | Result | 실행 결과를 지칭 | | ||
|
||
<br> | ||
|
||
|
@@ -28,6 +29,12 @@ | |
- [x] 이름은 빈문자 혹은 공백으로만 이루어지면 안 된다 | ||
|
||
|
||
- 사다리 게임 | ||
- [x] 사다리를 생성한다. | ||
- [x] 사다리 게임의 결과를 판단한다. | ||
- [ ] 보고싶은 사람의 사다리 게임의 결과를 전달한다. | ||
|
||
|
||
- 맵 (사다리) | ||
- [x] 사다리의 높이는 숫자여야 한다. | ||
- [x] 사다리의 최소 높이는 1이다. | ||
|
@@ -43,13 +50,34 @@ | |
- [x] 연속으로 연결상태를 가질 수 없다. | ||
|
||
|
||
- 참가자 | ||
- [x] 사람은 10명까지 ( 테스트 원할한 범위 ) | ||
- [x] 사람은 2명 이상이다. | ||
- [x] 사람이름은 ',' 로 구분한다. | ||
- [x] 중복된 이름을 가질 수 없다. | ||
|
||
|
||
- 결과들 | ||
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.
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. README 중복이라는 것은 README 파일이 두 개라는 의미가 맞을까요? docs에 넣은 이유는 크게 없었습니다...! 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.
아뇨, cf546ca 커밋 기준으로
👍 |
||
- [x] 결과는 사람 수 만큼이다. | ||
- [x] 결과는은 ',' 로 구분한다. | ||
- [x] all을 받은 경우 전체 결과를 반환한다. | ||
- [x] 사람 이름을 받은 경우 해당 사람의 결과를 반환한다. | ||
|
||
|
||
- 결과 | ||
- [x] 사다리의 결과는 최대 5글자까지 가능하다 | ||
- [x] 결과는 빈문자 혹은 공백으로만 이루어지면 안 된다 | ||
|
||
- 출력 | ||
- [x] 사람 이름은 5자 기준으로 출력하기에 폭도 이에 맞춘다. | ||
- [x] 보고 싶은 사람의 실행 결과를 출력한다. | ||
|
||
|
||
- 입력 | ||
- [x] 참여자 이름을 입력한다. | ||
- [x] 최대 사다리 높이를 입력한다. | ||
- [x] 실행 결과를 입력한다. | ||
- [x] 결과를 보고 싶은 사람의 이름을 입력한다. | ||
|
||
## 요구 사항 | ||
|
||
|
@@ -60,6 +88,10 @@ | |
- [x] 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다. | ||
- [x] |-----|-----| 모양과 같이 가로 라인이 겹치는 경우 어느 방향으로 이동할지 결정할 수 없다. | ||
<br> | ||
- [x] 실행 결과를 쉼표(,)를 기준으로 구분한다. | ||
- [x] 사다리 결과 출력 시 결과도 함께 출력한다. | ||
- [x] 결과를 보고 싶은 사람 이름을 입력한다. (all 입력 시 전체 결과 출력) | ||
- [x] all이 아닐 경우 결과 보고 싶은 사람 이름을 다시 물어야 한다. | ||
|
||
## 📌 Commit Convention | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,86 @@ | ||||||
package controller; | ||||||
|
||||||
import domain.*; | ||||||
import util.BooleanGenerator; | ||||||
import view.input.InputView; | ||||||
import view.output.OutputView; | ||||||
|
||||||
public class LadderGameController { | ||||||
|
||||||
private static final String GET_RESULT_ALL = "all"; | ||||||
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. GET은 붙이지 않아도 되지 않을까요?
Suggested change
|
||||||
|
||||||
public void play(InputView inputView, OutputView outputView, BooleanGenerator booleanGenerator) { | ||||||
Participants participants = setParticipants(inputView); | ||||||
Results results = setResults(inputView, participants); | ||||||
Ladder ladder = generateLadder(inputView, participants, booleanGenerator); | ||||||
|
||||||
LadderGame ladderGame = new LadderGame(participants, results, ladder); | ||||||
printLadder(outputView, ladderGame); | ||||||
|
||||||
printResult(inputView, outputView, ladderGame); | ||||||
} | ||||||
|
||||||
private Participants setParticipants(InputView inputView) { | ||||||
try { | ||||||
String participantNames = inputView.enterParticipantNames(); | ||||||
return new Participants(participantNames); | ||||||
} catch (IllegalArgumentException exception) { | ||||||
inputView.printErrorMessage(exception); | ||||||
return setParticipants(inputView); | ||||||
} | ||||||
} | ||||||
|
||||||
private Results setResults(InputView inputView, Participants participants) { | ||||||
try { | ||||||
String results = inputView.enterResults(); | ||||||
return new Results(results, participants.getParticipantCount()); | ||||||
} catch (IllegalArgumentException exception) { | ||||||
inputView.printErrorMessage(exception); | ||||||
return setResults(inputView, participants); | ||||||
} | ||||||
} | ||||||
|
||||||
private Ladder generateLadder(InputView inputView, Participants participants, BooleanGenerator booleanGenerator) { | ||||||
try { | ||||||
Height height = new Height(inputView.enterHeight()); | ||||||
Weight weight = new Weight(participants.getParticipantCount()); | ||||||
return new Ladder(height, weight, booleanGenerator); | ||||||
} catch (IllegalArgumentException exception) { | ||||||
inputView.printErrorMessage(exception); | ||||||
return generateLadder(inputView, participants, booleanGenerator); | ||||||
} | ||||||
} | ||||||
|
||||||
private void printLadder(OutputView outputView, LadderGame ladderGame) { | ||||||
outputView.printLadder(ladderGame.getParticipants(), ladderGame.getLadder(), | ||||||
ladderGame.getResults()); | ||||||
} | ||||||
|
||||||
private void printResult(InputView inputView, OutputView outputView, LadderGame ladderGame) { | ||||||
boolean isContinue = true; | ||||||
while (isContinue) { | ||||||
isContinue = getResult(inputView, outputView, ladderGame); | ||||||
} | ||||||
} | ||||||
|
||||||
private boolean getResult(InputView inputView, OutputView outputView, LadderGame ladderGame) { | ||||||
try { | ||||||
String inputResult = inputView.enterGetResult(); | ||||||
return getResultByInput(outputView, ladderGame, inputResult); | ||||||
} catch (IllegalArgumentException exception) { | ||||||
inputView.printErrorMessage(exception); | ||||||
return true; | ||||||
} | ||||||
} | ||||||
|
||||||
private boolean getResultByInput(OutputView outputView, LadderGame ladderGame, String inputValue) { | ||||||
if (GET_RESULT_ALL.equals(inputValue)) { | ||||||
outputView.printMatchAllResult(ladderGame.getGameAllResult(), | ||||||
ladderGame.getParticipants()); | ||||||
return false; | ||||||
} | ||||||
|
||||||
outputView.printMatchResult(ladderGame.getGameResultByName(inputValue)); | ||||||
return true; | ||||||
} | ||||||
} |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package domain; | ||
|
||
import exception.NotFindPersonException; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class GameResult { | ||
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 final Map<Person, Result> ladderResult; | ||
|
||
public GameResult(Map<Person, Result> ladderResult) { | ||
this.ladderResult = new HashMap<>(ladderResult); | ||
} | ||
|
||
public Map<Person, Result> getAllResult() { | ||
return ladderResult; | ||
} | ||
|
||
public Result getResultByName(String name) { | ||
Person findPerson = new Person(name); | ||
return ladderResult.entrySet() | ||
.stream() | ||
.filter(resultEntry -> resultEntry.getKey() | ||
.equals(findPerson)) | ||
.findFirst() | ||
.orElseThrow(NotFindPersonException::new) | ||
.getValue(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,16 +1,46 @@ | ||||||
package domain; | ||||||
|
||||||
import util.BooleanGenerator; | ||||||
|
||||||
import java.util.List; | ||||||
import java.util.stream.Collectors; | ||||||
import java.util.stream.IntStream; | ||||||
|
||||||
public class Ladder { | ||||||
|
||||||
private final List<Line> lines; | ||||||
|
||||||
public Ladder(List<Line> lines) { | ||||||
this.lines = lines; | ||||||
public Ladder(Height height, Weight weight, BooleanGenerator booleanGenerator) { | ||||||
this.lines = generate(height, weight, booleanGenerator); | ||||||
} | ||||||
|
||||||
private List<Line> generate(Height height, Weight weight, BooleanGenerator booleanGenerator) { | ||||||
return IntStream.range(0, height.getHeight()) | ||||||
.mapToObj((count) -> new Line(weight.getWeight(), booleanGenerator)) | ||||||
.collect(Collectors.toList()); | ||||||
} | ||||||
|
||||||
public List<Line> getLines() { | ||||||
return List.copyOf(lines); | ||||||
return lines; | ||||||
} | ||||||
|
||||||
public int getResultIndex(int index) { | ||||||
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. 단순히 index라는 변수명이 아니라 좀 더 명확하게 어떤 인덱스인지 말해주면 좋지 않을까요? 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. 의견을 보고 participnatIndex로 했지만, Ladder에서는 참여자 인덱스인 것은 알 필요가 없다고 판단해 startIndex로 결정했습니다. 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. 저는 participantIndex로 하는 게 좋지 않을까?라는 생각이었는데요. 말씀대로 Ladder 도메인에서 참여자 인덱스는 굳이 알 필요 없는 게 더 나을 것 같습니다. 👍 |
||||||
int resultIndex = index; | ||||||
for (Line line : lines) { | ||||||
resultIndex = getNextIndex(index, line); | ||||||
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. 도메인의 중요한 부분이 잘못된 것 같습니다. getNextIndex의 인자로 index를 받고 있어서 매번 같은 인자로 받게 됩니다. 이 부분 때문에 Ladder의 lines 필드를 아래와 같이 넣고 테스트해보면 결과값이 틀리게 나옵니다.
아래처럼 수정이 필요하지 않을까요?
Suggested change
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. 정말 바보 같은 실수네요... 🥲 테스트 때 잡히지 않는 것을 보니 테스트도 부실했었다는 생각이 듭니다... 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 resultIndex; | ||||||
} | ||||||
|
||||||
private int getNextIndex(int index, Line line) { | ||||||
if (line.canMoveLeft(index)) { | ||||||
return index - 1; | ||||||
} | ||||||
if (line.canMoveRight(index)) { | ||||||
return index + 1; | ||||||
} | ||||||
|
||||||
return index; | ||||||
Comment on lines
+37
to
+44
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. 로직이 깔끔해서 좋았어요 👍 |
||||||
} | ||||||
} |
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.
넵, 잘해주셨어요! Controller가 말 그대로 뷰와 모델의 중간에서 컨트롤하는 역할이라고 보시면 됩니다. (링크)
네 맞습니다! 👍 OutputView가 도메인을 아예 모르는 상태가 되면 도메인을 의존하지 않고 확장가능하다는 이야기를 하고싶었습니다.
현재도 충분히 객체지향에 맞는 코드라고 생각합니다. 굳이 Validator 클래스로 빼지 않아도 될 것 같아요. (빼도 좋고 안 빼도 좋습니다)
Controller의 역할이 커지는 것 같지만 현재 미션에서는 Controller에서 해도 괜찮다고 생각합니다. 다른 입력을 통해 결과물을 달리 준다는 역할을 분리한 하나의 클래스에서 진행하게 된다면 DispatcherServlet가 하는 역할과 비슷할 것 같은데요. DispatcherServlet처럼 다른 클래스로 또 나눌 수도 있을 것 같지만 현재 미션에서 적용하기보단 추후 웹 미션에서 적용해보면 좋을 것 같습니다.
GameResult는 Map 형태로 저장하고 있는 것 같은데요. GameResult가 맞을까요? 다른 객체로 인식되는 부분은 아래 답변처럼 equals와 hashcode를 재정의하면 해결되는 문제같습니다. 현재 상황에서는 재정의해도 된다고 생각되고요.
Result 자체도 하나의 value로서 특정될 수 있는 것 같은데요. equals와 hashcode를 재정의하면될 것 같습니다.