-
Notifications
You must be signed in to change notification settings - Fork 0
[다리 건너기] 4주차 미션 리펙토링 #1
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
d2f23c7
178292b
621de17
a591144
05d438b
3390a86
4fe2890
3a2cec0
1043dba
d9f6d4a
d80e5e4
811ca2b
99a031b
d5c9b1f
ace1bda
315e1aa
b357bbb
f9afb89
f9abe30
883f021
b63c2bb
b0592ef
68e366c
691ecff
108d561
e632b37
db5f8fa
d34ae10
615ac5f
82014b6
6677cfc
bf56ff0
22b52c1
b364ef6
222b860
eabcc75
621cccf
1d7c76b
e07828e
fc1d8fc
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,39 @@ | ||
# 미션 - 다리 건너기 | ||
|
||
## 기능 목록 | ||
|
||
### 입력 | ||
|
||
- 다리의 길이를 입력하는 기능 | ||
- 입력 값이 숫자인지 검증하는 기능 | ||
- 입력 값이 `3 ~ 20` 사이의 숫자인지 검증하는 기능 | ||
- 이동할 칸을 입력하는 기능 | ||
- 입력 값이 한 글자의 대문자인지 검증하는 기능 | ||
- 입력 값이 `U` 또는 `D`인지 검증하는 기능 | ||
- 게임 재시작 유무를 입력하는 기능 | ||
- 입력 값이 한 글자의 대문자인지 검증하는 기능 | ||
- 입력 값이 `R` 또는 `Q`인지 검증하는 기능 | ||
|
||
### 출력 | ||
|
||
- 게임 시작 안내 문구를 출력하는 기능 | ||
- 다리 길이 입력 안내 문구를 출력하는 기능 | ||
- 이동할 칸 입력 안내 문구를 출력하는 기능 | ||
- 플레이어가 지금까지 이동한 경로를 출력하는 기능 | ||
- 게임 재시작 입력 안내 문구를 출력하는 기능 | ||
- 최종 게임 결과를 출력하는 기능 | ||
- 플레이어의 마지막 이동 경로를 출력하는 기능 | ||
- 플레이어 게임 성공 유무를 출력하는 기능 | ||
- 플레이어가 게임을 시도한 횟수를 출력하는 기능 | ||
- 예외 발생 시 예외를 출력하는 기능 | ||
|
||
### 로직 | ||
|
||
- 입력한 다리 길이를 가지는 다리를 생성하는 기능 | ||
- 플레이어가 다리를 이동하는 기능 | ||
- 플레이어가 입력한 대로 다리의 칸을 입력할 수 있는지 확인하는 기능 | ||
- 플레이어가 다리를 모두 건넜는지 확인하는 기능 | ||
- 게임을 재시작하는 기능 | ||
- 플레이어의 이동 경로를 초기화하는 기능 | ||
- 플레이어의 게임 시도 횟수를 `1` 증가시키는 기능 | ||
- 예외 발생 시 예외가 발생한 단계를 다시 진행하는 기능 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# 미션 - 다리 건너기 | ||
|
||
## 리펙토링 목록 | ||
|
||
- `PlayerState`와 `Bridge`간 순환 참조 제거 | ||
- `GameCommand`에서 사용하고 있던 잘못된 이름 수정 | ||
- 해당 클래스에서 사용하는 상수 및 메세지를 모두 내부에서 관리 | ||
- 불필요한 `GameStatus` 일부 상태 삭제 | ||
- `GuideView`에서 출력하는 메세지를 `OutputView`로 통합 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
package bridge; | ||
|
||
import bridge.domain.game.GameStatus; | ||
|
||
public class Application { | ||
|
||
public static void main(String[] args) { | ||
// TODO: 프로그램 구현 | ||
GameRunner.run(GameStatus.MAKE_BRIDGE); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package bridge; | ||
|
||
import bridge.controller.GameController; | ||
import bridge.domain.game.GameStatus; | ||
import bridge.view.IOViewResolver; | ||
import bridge.view.InputView; | ||
import bridge.view.OutputView; | ||
|
||
public final class GameRunner { | ||
|
||
private GameRunner() { | ||
} | ||
|
||
public static void run(GameStatus gameStatus) { | ||
IOViewResolver ioViewResolver = new IOViewResolver(InputView.getInstance(), OutputView.getInstance()); | ||
GameController controller = new GameController(ioViewResolver); | ||
|
||
while (gameStatus.playable()) { | ||
gameStatus = controller.process(gameStatus); | ||
} | ||
} | ||
} | ||
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package bridge.controller; | ||
|
||
import bridge.BridgeRandomNumberGenerator; | ||
import bridge.domain.bridge.BridgeGame; | ||
import bridge.domain.bridge.exception.WrongGeneratorException; | ||
import bridge.domain.game.GameStatus; | ||
import bridge.domain.player.exception.WrongBridgeTileException; | ||
import bridge.dto.controller.ExitDto; | ||
import bridge.dto.controller.MoveDto; | ||
import bridge.dto.controller.RetryDto; | ||
import bridge.dto.input.ReadBridgeSizeDto; | ||
import bridge.dto.input.ReadGameCommandDto; | ||
import bridge.dto.input.ReadMovingDto; | ||
import bridge.dto.output.PrintExceptionDto; | ||
import bridge.dto.output.PrintResultDto; | ||
import bridge.view.IOViewResolver; | ||
import bridge.view.exception.NotFoundViewException; | ||
import java.util.EnumMap; | ||
import java.util.Map; | ||
import java.util.function.Supplier; | ||
|
||
public class GameController { | ||
|
||
private static final String APPLICATION_EXCEPTION_MESSAGE = "애플리케이션 구성에 문제가 발생했습니다."; | ||
|
||
private final IOViewResolver ioViewResolver; | ||
private final Map<GameStatus, Supplier<GameStatus>> gameStatusMappings; | ||
private BridgeGame bridgeGame; | ||
|
||
public GameController(final IOViewResolver ioViewResolver) { | ||
this.ioViewResolver = ioViewResolver; | ||
gameStatusMappings = new EnumMap<>(GameStatus.class); | ||
|
||
initGameStatusMappings(); | ||
} | ||
|
||
private void initGameStatusMappings() { | ||
gameStatusMappings.put(GameStatus.MAKE_BRIDGE, this::makeBridge); | ||
gameStatusMappings.put(GameStatus.GAME_PLAY, this::gamePlay); | ||
gameStatusMappings.put(GameStatus.GAME_OVER, this::gameOver); | ||
gameStatusMappings.put(GameStatus.GAME_EXIT, this::gameExit); | ||
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. @eunkeeee 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. @apptie 아하.. 저도 처음에는 신박한데 복잡해 보인다고 생각했었는데, |
||
} | ||
|
||
public GameStatus process(GameStatus gameStatus) { | ||
try { | ||
return gameStatusMappings.get(gameStatus).get(); | ||
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. @eunkeeee |
||
} catch (IllegalArgumentException e) { | ||
return processGameException(e.getMessage(), gameStatus); | ||
} catch (WrongGeneratorException | NotFoundViewException | WrongBridgeTileException e) { | ||
return processApplicationException(e.getMessage()); | ||
} catch (IndexOutOfBoundsException | NullPointerException e) { | ||
e.printStackTrace(); | ||
return processApplicationException(APPLICATION_EXCEPTION_MESSAGE); | ||
} | ||
} | ||
|
||
private GameStatus processGameException(String message, final GameStatus gameStatus) { | ||
ioViewResolver.outputViewResolve(new PrintExceptionDto(message)); | ||
return gameStatus; | ||
} | ||
|
||
private GameStatus processApplicationException(String message) { | ||
System.out.println(message); | ||
return GameStatus.APPLICATION_EXIT; | ||
} | ||
|
||
private GameStatus makeBridge() { | ||
ReadBridgeSizeDto inputDto = ioViewResolver.inputViewResolve(ReadBridgeSizeDto.class); | ||
BridgeRandomNumberGenerator generator = new BridgeRandomNumberGenerator(); | ||
bridgeGame = new BridgeGame(inputDto.getSize(), generator); | ||
|
||
return GameStatus.GAME_PLAY; | ||
} | ||
|
||
private GameStatus gamePlay() { | ||
ReadMovingDto dto = ioViewResolver.inputViewResolve(ReadMovingDto.class); | ||
MoveDto moveDto = bridgeGame.move(dto); | ||
|
||
ioViewResolver.outputViewResolve(moveDto.getPrintMapDto()); | ||
return moveDto.getNextGameStatus(); | ||
} | ||
|
||
private GameStatus gameOver() { | ||
ReadGameCommandDto inputDto = ioViewResolver.inputViewResolve(ReadGameCommandDto.class); | ||
RetryDto retryDto = bridgeGame.retry(inputDto); | ||
|
||
return retryDto.getNextGameStatus(); | ||
} | ||
|
||
private GameStatus gameExit() { | ||
ExitDto exitDto = bridgeGame.exit(); | ||
|
||
ioViewResolver.outputViewResolve(new PrintResultDto(exitDto)); | ||
return GameStatus.APPLICATION_EXIT; | ||
} | ||
} |
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.
지민님 혹시
Runner
와controller
는 어떤 차이가 있나요??지민님이 구현하고자 하는 모델은 어떤 모델인지 궁금합니다
저는 MVC 모델 규칙을 최대한 지키며 간단하게 만들려고 노력하고 있어요
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.
@eunkeeee
저 또한 MVC 모델 규칙을 지키면서 미션을 진행하고자 노력하고 있습니다.
다만 저는 애플리케이션의 생명 주기를
Controller
에서 관리하는 것은 어울리지 않다고 생각했었습니다.Controller
는 단순히 게임 진행 상황GameStatus
에 따라View
에서 받은 데이터를 토대로Model
에서 로직을 수행하는 것이 전부라고 생각했고, 그 이상으로 책임을 가지는 것은 어색하다고 느꼈습니다.그래서
Controller
는 애플리케이션 사용자의 요청을 전달받고, 그 요청을 처리하고, 요청에 따른 응답을GameStatus
를 반환하도록 했고, 이러한Controller
를 애플리케이션의 생명 주기에 따라 호출하기 위한 유틸리티 클래스가GameRunner
라고 보시면 될 것 같습니다.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.
@apptie 아하.. 애플리케이션 생명 주기를 관리하는 변수인
GameStatus
를 컨트롤러에서 분리한 것이군요..객체에 대한 지민님의 고민이 많이 느껴져요 !