728x90
서론
- 이제 실제 콘솔 애플리케이션이 동작하도록 실제 View와 Controller의 결합을 해보도록 하겠습니다.
View
- 실제 사용자가 값을 입력하고, 로직이 실행된 뒤의 결과를 출력하기 위한 계층으로 우리는 콘솔 애플리케이션이니 입력은 Scanner 를 통해 받고, 출력은 System.out.println 을 통해 합니다.
public static int inputGameRecordId() {
System.out.println("게임 기록을 조회할 ID를 입력해주세요.");
return scanner.nextInt();
}
- 입력 받는 값은 게임 기록을 조회할 ID입니다.
- 단순히 이걸 입력 받을 수 있는 메서드를 만들어서 처리해주면 됩니다.
package baseball.view;
import baseball.dto.CheckBallResponse;
import baseball.dto.GameRecordResponse;
import baseball.dto.GameRecordsResponse;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
public class OutputView {
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd hh:mm:ss";
private static final String DELIMITER = "";
private OutputView() {
}
public static void printExitMessage() {
System.out.println("애플리케이션이 종료되었습니다.");
}
public static void printResult(final CheckBallResponse checkBallResponse) {
if (checkBallResponse.isNotting()) {
System.out.println("낫싱");
return;
}
printStrikeAndBallCount(checkBallResponse.strikeCount(), checkBallResponse.ballCount());
printGameSuccessMessage(checkBallResponse.isSuccess());
}
public static void printPickComputerNumbers() {
System.out.println("컴퓨터가 숫자를 뽑았습니다.");
}
public static void printErrorMessage(final String message) {
System.out.println(message);
}
public static void printGameRecords(final List<GameRecordsResponse> gameRecords) {
System.out.println("게임 기록");
if (gameRecords.isEmpty()) {
System.out.println("기록이 없습니다.");
System.out.println("-------기록 종료-------");
return;
}
for (final GameRecordsResponse gameRecord : gameRecords) {
final String stringBuilder = "[" + gameRecord.id() + "] " +
"시작시간: " +
gameRecord.startAt().format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)) +
" / " +
"종료시간:" + gameRecord.endAt().format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)) +
" / " +
"횟수: " + gameRecord.playerTimes();
System.out.println(stringBuilder);
}
}
public static void printGameRecord(final GameRecordResponse gameRecord) {
System.out.println(gameRecord.id() + "번 게임 결과");
gameRecord.playerRecordResponses().forEach(playerRecord -> {
final String playerNumber = playerRecord.numbers()
.stream()
.map(String::valueOf)
.collect(Collectors.joining(DELIMITER));
System.out.println("숫자를 입력해주세요: " + playerNumber);
if (playerRecord.isNotting()) {
System.out.println("낫싱");
return;
}
printStrikeAndBallCount(playerRecord.strikeCount(), playerRecord.ballCount());
printGameSuccessMessage(playerRecord.isSuccess());
});
System.out.println("-------기록 종료-------");
}
private static void printStrikeAndBallCount(final int strikeCount, final int ballCount) {
System.out.println(strikeCount + "스트라이크 " + ballCount + "볼");
}
private static void printGameSuccessMessage(final boolean isSuccess) {
if (isSuccess) {
System.out.println("3개의 숫자를 모두 맞히셨습니다.");
System.out.println("-------게임 종료-------");
}
}
}
- 기록에 맞게 View에 코드를 짜주면 됩니다.
- 큰 어려운 로직은 없어서 따로 설명은 하지 않을려고 하빈다.
- 그러나 기존에 코드와 중복코드들이 존재할 수 있습니다. 그런 부분들을 메서드로 추출해서 코드를 제거해줍니다.
Application
package baseball;
import baseball.controller.BaseBallGameController;
import baseball.domain.Commend;
import baseball.dto.CheckBallResponse;
import baseball.dto.CheckBallsRequest;
import baseball.dto.GameRecordResponse;
import baseball.dto.GameRecordsResponse;
import baseball.generator.BaseBallNumberGenerator;
import baseball.generator.BaseBallNumberShuffleGenerator;
import baseball.repository.GameRepositoryImpl;
import baseball.view.InputView;
import baseball.view.OutputView;
import java.util.List;
public class GameApplication {
private static final BaseBallNumberGenerator baseBallNumberGenerator = new BaseBallNumberShuffleGenerator();
private static final BaseBallGameController baseBallGameController = new BaseBallGameController(new GameRepositoryImpl());
public static void run() {
Commend commend = Commend.END;
try {
do {
commend = Commend.of(InputView.inputMenu());
if (commend == Commend.START) {
final int gameId = baseBallGameController.gameStart(baseBallNumberGenerator);
OutputView.printPickComputerNumbers();
gameInProgress(gameId);
} else if (commend == Commend.GAME_RECORD) {
final List<GameRecordsResponse> gameRecords = baseBallGameController.getGames();
OutputView.printGameRecords(gameRecords);
final int gameId = InputView.inputGameRecordId();
final GameRecordResponse game = baseBallGameController.getGame(gameId);
OutputView.printGameRecord(game);
}
}
while (commend != Commend.END);
applicationEnd();
} catch (final Exception e) {
OutputView.printErrorMessage(e.getMessage());
run();
}
}
private static void applicationEnd() {
OutputView.printExitMessage();
}
private static void gameInProgress(final int gameId) {
try {
boolean isFinished = true;
while (isFinished) {
final List<Integer> userNumbers = InputView.inputNumbers();
final CheckBallsRequest checkBallsRequest = new CheckBallsRequest(userNumbers, gameId);
final CheckBallResponse checkBallResponse = baseBallGameController.checkBalls(checkBallsRequest);
OutputView.printResult(checkBallResponse);
isFinished = !checkBallResponse.isSuccess();
}
} catch (final Exception e) {
OutputView.printErrorMessage(e.getMessage());
gameInProgress(gameId);
}
}
}
- 해당 메서드에선 각 View Controller를 연결해서 처리하는 행위를 해줍니다.
- 실제 웹 애플리케이션과는 다르지만, 여기서 최대한 사용자 입력과 출력에 대한 부분들을 Controller에게 전달하는 것을 목표로 하였습니다.
- if문에 이번엔 GAME_RECORD를 추가해 처리하도록 로직을 작성하였습니다.
public class Application {
public static void main(String[] args) {
GameApplication.run();
}
}
- 마지막 main 메서드에서는 GameApplication의 run 메서드만 호출하면 끝입니다.
간단한 회고
- 이번엔 CRUD에서 R을 초점을 맞추는 작업을 해봤습니다.
- Step2부터는 실제 했던 숫자야구게임을 좀 더 요구사항을 추가하여 진행하고 있습니다.
- 초반에 Game이라는 도메인을 만들지 않아, 지금처럼 확장하려고 할때 어려움이 있었던거 같습니다.
- 이번에 Game이라는 도메인을 만들어 아키텍처를 변경하였는데, 아키텍처를 변경하는 작업은 쉬운게 아니라는걸 깨닫는거 같습니다.
결론
- 이제 다음 Step3로 넘어갑니다.
- Step3의 요구사항은 통계입니다. 게임을 진행했던 부분들에 대한 간단한 통계를 보여줄 예정이빈다.
- 간단한 와이어 프레임을 같이 첨부합니다.
게임을 새로 시작하려면 1, 기록을 보려면 2, 통계를 보려면 3, 종료하려면 9을 입력하세요.
1
컴퓨터가 숫자를 뽑았습니다.
숫자를 입력해주세요 : 123
1볼 1스트라이크
숫자를 입력해주세요: 145
1볼
숫자를 입력해주세요: 671
2볼
숫자를 입력해주세요: 216
1스트라이크
숫자를 입력해주세요: 713
3스트라이크
3개의 숫자를 모두 맞히셨습니다.
-------게임 종료-------
게임을 새로 시작하려면 1, 기록을 보려면 2, 통계를 보려면 3, 종료하려면 9을 입력하세요.
2
- [1] / 시작시간: 2024. 04. 07 23:12 / 종료시간: 2024. 04. 07 23:13 / 횟수: 5
게임 기록을 조회할 ID를 입력해주세요.
1
숫자를 입력해주세요 : 123
1볼 1스트라이크
숫자를 입력해주세요: 145
1볼
숫자를 입력해주세요: 671
2볼
숫자를 입력해주세요: 216
1스트라이크
숫자를 입력해주세요: 713
3스트라이크
3개의 숫자를 모두 맞히셨습니다.
-------게임 종료-------
-------기록 종료-------
게임을 새로 시작하려면 1, 기록을 보려면 2, 통계를 보려면 3, 종료하려면 9을 입력하세요.
3
가장 적은 횟수: 5회 - [1]
가장 많은 횟수: 5회 - [1]
평균횟수: 5회
-------통계 종료-------
게임을 새로 시작하려면 1, 기록을 보려면 2, 통계를 보려면 3, 종료하려면 9을 입력하세요.
9
애플리케이션이 종료되었습니다.
- 전체적인 Step2의 애플리케이션의 코드는 아래서 확인가능합니다.
- GitHub - ksy90101/java-baseball at step2
- 이 글과 관련된 피드백이 있다면 언제든 댓글로 남겨주세요!
728x90
728x90
'Backend > Java' 카테고리의 다른 글
[숫자야구게임 Step3] Repository 구현 (0) | 2024.09.20 |
---|---|
[숫자야구게임 Step3] 정책을 정의내리고 테크스펙을 작성해보자. (0) | 2024.09.20 |
[숫자야구게임 Step2] 비지니스 로직을 작성하자. (0) | 2024.04.24 |
[숫자야구게임 Step2] 도메인 구현 (2) | 2024.04.24 |
Five API Performance Optimization Tricks that Every Java Developer Must Know(모든 자바 개발자가 알아야 할 다섯 가지 API 성능 최적화 팁) (0) | 2024.04.20 |