Activities/우아한 테크 프리코스
[회고록] 우아한테크 프리코스 회고록1-2
발달중인 망고
2023. 10. 26. 00:02
작성시각 10월 22일 오전 02:22 (이 포스팅은 1주 차 과제가 끝난 뒤에 자동 업로드됩니다.)
어느덧 10월 22일 4일차쯤 됐으려나요.. 그냥 제출하기 그래서 우테코 프리코스 디스코드를 탐방하던 중 MVC 이야기가 많이 나와서 그냥 대입해 보기로 했습니다.
많이 허접한데 지금 Controller, Model, View 개념도 다시 익히고 있어서 천천히 바꿔보려합니다. 가장 어려운 건 모델 부분인 것 같은데요.
Controller
더보기
Controller 코드 부분
package baseball.Controller;
import baseball.Model.BaseBallGame;
import baseball.Model.NumberGenerator;
import baseball.View.GameView;
import java.util.List;
public class GameController {
NumberGenerator numberGenerator = new NumberGenerator();
BaseBallGame baseBallGame = new BaseBallGame(numberGenerator);
GameView gameView = new GameView();
private static final int BALL = 0;
private static final int STRIKE = 1;
public void startGame() {
gameView.printStartMessage();
while (!baseBallGame.isGameOver()) {
String input = gameView.printInputMessage();
List<Integer> userInput = baseBallGame.parseUserInput(input);
List<Integer> ballStrikeCount = baseBallGame.checkBallCount(userInput);
int balls = ballStrikeCount.get(BALL);
int strikes = ballStrikeCount.get(STRIKE);
if (balls != 0 && strikes == 0) {
gameView.printBallMessage(balls);
} else if (balls != 0 && strikes != 0) {
gameView.printBallStrikeMessage(balls);
}
if (strikes != 0) {
gameView.printStrikeMessage(strikes);
}
if (balls == 0 && strikes == 0) {
gameView.printNothingMessage();
}
baseBallGame.gameOverCheck(strikes);
if (baseBallGame.isGameOver()) {
String inputRestart = gameView.printGameOverMessage();
baseBallGame.restartGame(inputRestart);
}
}
}
}
이게 제가 노력해본 GameController인데 부족한 점이 많이 보입니다. (사실 걍 쓰레기임 애정붙은 쓰레기)
회고록이라 대충쓰지만 그래도 좀 정리해 보겠습니다.
일단 대충 보이는 문제점 [Controller 편]
- 조건문을 사용해서 view를 컨트롤하는 게 너무 더러워 보임 딱 봐도 아닌 거 같아서 리펙토링예정
- 매직넘버를 지우겠다고 Controller 내에 정적변수를 선언하는 게 MVC에 맞지 않아 보입니다.
저도 정확한 건 아니어서 틀린 점이 있다면 피드백 부탁드립니다.
다음은 Model로 넘어가겠습니다.
Model
더보기
Model 코드 부분
package baseball.Model;
import java.util.ArrayList;
import java.util.List;
public class BaseBallGame {
/**
* Model은 Controller와 View에 관련된 코드가 있으면 안된다!!!!!!
* <p>
* 본 클래스는 게임의 전체적인데이터와 로직을 관리합니다.
*/
private List<Integer> computerNumber;
private NumberGenerator numberGenerator;
private boolean isGameOver;
private static final int BASEBALL_NUM_SIZE = 3;
public BaseBallGame(NumberGenerator numberGenerator) {
this.numberGenerator = numberGenerator;
computerNumber = numberGenerator.generatorComputerNumber(BASEBALL_NUM_SIZE);
isGameOver = false;
}
/**
* 유저의 입력을 받아 볼과 스트라이크를 알려주는 메소드
*/
public List<Integer> checkBallCount(List<Integer> userInput) {
List<Integer> listBallStrike = new ArrayList<>();
int totalCount = 0;
int strikeCount = 0;
int ballCount = 0;
if (userInput.size() != BASEBALL_NUM_SIZE) {
throw new IllegalArgumentException("입력 자릿 수 오류");
}
for (int i = 0; i < BASEBALL_NUM_SIZE; i++) {
if (userInput.contains(computerNumber.get(i))) {
totalCount++;
}
if (userInput.get(i) == computerNumber.get(i)) {
strikeCount++;
}
}
ballCount = totalCount - strikeCount;
listBallStrike.add(ballCount);
listBallStrike.add(strikeCount);
return listBallStrike;
}
/**
* 게임을 다시 시작할때 셋팅해주는 메소드
*/
public void restartGame(String userInput) {
if (userInput.equals("1")) {
computerNumber = numberGenerator.generatorComputerNumber(BASEBALL_NUM_SIZE);
isGameOver = false;
return;
}
if (userInput.equals("2")) {
isGameOver = true;
return;
}
throw new IllegalArgumentException("허가되지 않은 문자열");
}
/**
* 게임이 현재 끝난 상태인지 반환함
*/
public boolean isGameOver() {
return isGameOver;
}
/**
* 게임이 끝났는지 체크해줌
*/
public void gameOverCheck(int strike) {
if (strike == BASEBALL_NUM_SIZE) {
isGameOver = true;
}
}
/**
* 유저가 입력한 String형식의 Input을 List형식으로 파씽함
*/
public List<Integer> parseUserInput(String input) {
List<Integer> parsedInput = new ArrayList<>();
if (input.length() != BASEBALL_NUM_SIZE) {
throw new IllegalArgumentException("입력 자릿 수 오류");
}
for (int i = 0; i < BASEBALL_NUM_SIZE; i++) {
char c = input.charAt(i);
if (c == '0') {
throw new IllegalArgumentException("허가되지 않은 문자열");
}
if (Character.isDigit(c)) {
int digit = Character.getNumericValue(c);
parsedInput.add(digit);
}
if (!Character.isDigit(c)) {
throw new IllegalArgumentException("허가되지 않은 문자열");
}
}
return parsedInput;
}
}
일단 Model 자체가 게임 로직과 데이터를 처리하고 숫자 생성, 입력 유효성 검사, 게임 상태 관리 등을 담당하기에 다 때려 박았는데 이건 정말 아닌 것 같습니다. ㅋㅋㅋㅋㅋㅋ (NumberGenerator까지 다루면 너무 길어서 생략하겠습니다.)
일단 대충 보이는 문제점 [Model 편]
- Model자체가 담당하는 일은 하고 있지만 구성자체가 원시적이라는 느낌이 듭니다.
- Computer, Player, 그리고 나머지 연산을 해주는 어떤 Class로 Model을 분리하고 세분화할 예정입니다.
- 예외처리도 그냥 딱 봐도 더러워 보입니다. 모아서 어딘가에 저장한 뒤에 호출해 사용하는 식으로 해야겠습니다.
마찬가지로 개념에 문제가 있다면 피드백 부탁드립니다.
View
더보기
View 코드 부분
package baseball.View;
import camp.nextstep.edu.missionutils.Console;
public class GameView {
/**
* Veiw는 Model에만 의존해야 하고, Controller에는 의존하면 안된다. Model로 부터 데이터를 받을때는, 사용자마다 다르게 보여주어야하는 데이터에 대해서만 받아야한다. 우리는근데 유저마다
* 다를게 없기에 의존하지 않는다는 원칙을 따른다.
*/
public void printStartMessage() {
System.out.println("숫자 야구 게임을 시작합니다.");
}
public void printBallStrikeMessage(int ball) {
System.out.print(ball + "볼 ");
}
public void printBallMessage(int ball) {
System.out.println(ball + "볼");
}
public void printStrikeMessage(int strike) {
System.out.println(strike + "스트라이크");
}
public void printNothingMessage() {
System.out.println("낫싱");
}
public String printGameOverMessage() {
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
return Console.readLine();
}
public String printInputMessage() {
System.out.println("숫자를 입력해주세요 : ");
return Console.readLine();
}
}
여기는 그나마 구현이 쉬웠는데 제 수준에서는 어떻게 바꾸면 최적화가 될지 보이지 않네요...
ㅋㅋㅋㅋ어느덧 47 커밋이 넘어가는 게 웃겨서 캡처
뭐 이 정도입니다. 하루종일 보고 있는데 차츰차츰 해 나가려 합니다.
모두들 파이팅!