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 커밋이 넘어가는 게 웃겨서 캡처

 

뭐 이 정도입니다. 하루종일 보고 있는데 차츰차츰 해 나가려 합니다. 

모두들 파이팅!