Skip to content
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

숫자 야구게임 구현 #2774

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4fe02a2
git first commit - 어느정도 틀 구현, 노트북 -> PC로 옮기기 위해 브랜치 x
tjdxo1193 Nov 1, 2023
f86ddca
구현은 완료했다. 이제 리펙토링을 해야한다.
tjdxo1193 Nov 3, 2023
5db856c
잘못된 입력에 대한 커스텀 예외 생성 및 message setting
tjdxo1193 Nov 4, 2023
5cfbeda
유효한 값 체크하는 메서드 구현 및 예외 복구로 처리했음
tjdxo1193 Nov 4, 2023
2793756
코드 정리 및 주석
tjdxo1193 Nov 4, 2023
52b8e37
import 정리
tjdxo1193 Nov 4, 2023
6eb2d7b
Merge pull request #1 from tjdxo1193/exception
tjdxo1193 Nov 4, 2023
1a1e3cd
[테스트 수행 중 failed 수정] 메세지 출력 오타 및 메세지 출력 프로세스 살짝 수정
tjdxo1193 Nov 4, 2023
aac9f69
지원해주는 api를 사용하여 사용자 입력값과 랜덤수를 가져옴
tjdxo1193 Nov 4, 2023
01cbfdb
기반 필수 클래스 생성
tjdxo1193 Nov 4, 2023
e420c89
메소드 분리 완료 todo 아쉬운점 ..
tjdxo1193 Nov 4, 2023
4bec3d6
Merge pull request #2 from tjdxo1193/리팩토링_1차
tjdxo1193 Nov 4, 2023
cb3a5f1
제목 없는 다이어그램.drawio이 추가되었습니다.
tjdxo1193 Nov 6, 2023
81c2f92
객체지향적 설계 및 재리팩토링
tjdxo1193 Nov 6, 2023
2cfe1de
Merge remote-tracking branch 'origin/main'
tjdxo1193 Nov 6, 2023
7201201
제목 없는 다이어그램.drawio 업데이트
tjdxo1193 Nov 6, 2023
ec16338
도메인 설계 문서 작성
tjdxo1193 Nov 7, 2023
91a03fc
Answer생성자를 통해 각 도메인 별로 파라미터에 따라 다르게 생성하는 로직 구현
tjdxo1193 Nov 7, 2023
0a41f1c
게임을 종료 할지 다시할지 1,2의 코드를 ReplyOrNot enum으로 정의
tjdxo1193 Nov 7, 2023
0fe393b
값에 대한 휴효성 검증 하는 메서드 작성
tjdxo1193 Nov 7, 2023
e70e394
메서드 책임 분리, 자잘한 오타 수정
tjdxo1193 Nov 9, 2023
e237bcc
결과 result를 판단하여 생성하고 결과를 출력하는 로직 구현
tjdxo1193 Nov 9, 2023
b3642f0
출력 줄바꿈 수정
tjdxo1193 Nov 9, 2023
81e5708
절차지향적으로 설계했던 패키지(이전 완성본) 삭제
tjdxo1193 Nov 9, 2023
1e13076
테스트 코드 패키지 변경
tjdxo1193 Nov 9, 2023
94b9fd1
Merge pull request #3 from tjdxo1193/Refactoring_OOP_#1
tjdxo1193 Nov 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ repositories {

dependencies {
implementation 'com.github.woowacourse-projects:mission-utils:1.1.0'
implementation 'org.projectlombok:lombok:1.18.22'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

학습하실 때는 롬복 및 외부 라이브러리 사용 지양해주세요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 네!

}

java {
Expand Down
60 changes: 60 additions & 0 deletions docs/제목 없는 다이어그램.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<mxfile host="app.diagrams.net" modified="2023-11-06T15:05:38.514Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" etag="ldBo5bSzdiYxctWy_cm0" version="22.0.8" type="github">
<diagram name="페이지-1" id="q04Y4RyBtX_a_hriLJLF">
<mxGraphModel dx="1195" dy="632" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="nZR88hf0O_DFail2BoQR-1" value="Game" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="110" y="350" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-2" value="Computer" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="420" y="270" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-3" value="Judgment" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="420" y="470" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-4" value="Player" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="420" y="370" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-6" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="nZR88hf0O_DFail2BoQR-1" target="nZR88hf0O_DFail2BoQR-2">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="340" y="480" as="sourcePoint" />
<mxPoint x="390" y="430" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-8" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="nZR88hf0O_DFail2BoQR-1" target="nZR88hf0O_DFail2BoQR-4">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="240" y="375" as="sourcePoint" />
<mxPoint x="430" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-9" value="정답을 생성" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="280" y="300" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-10" value="정답을 입력" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="300" y="360" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-11" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="nZR88hf0O_DFail2BoQR-1" target="nZR88hf0O_DFail2BoQR-3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="520" as="sourcePoint" />
<mxPoint x="300" y="625" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-12" value="정답인지 판단" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="320" y="430" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="nZR88hf0O_DFail2BoQR-14" value="" style="curved=1;endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="nZR88hf0O_DFail2BoQR-1" target="nZR88hf0O_DFail2BoQR-1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="460" as="sourcePoint" />
<mxPoint x="100" y="380" as="targetPoint" />
<Array as="points">
<mxPoint x="100" y="450" />
<mxPoint x="50" y="410" />
<mxPoint x="50" y="380" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
45 changes: 45 additions & 0 deletions src/main/java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다.
예) 상대방(컴퓨터)의 수가 425일 때
123을 제시한 경우 : 1스트라이크
456을 제시한 경우 : 1볼 1스트라이크
789를 제시한 경우 : 낫싱
위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다.
컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다.
게임 플레이어는 컴퓨터가 생각하고 있는 서로 다른 3개의 숫자를 입력하고,
컴퓨터는 입력한 숫자에 대한 결과를 출력한다.
이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.

사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.

# 요구사항 분석
- 컴퓨터가 수를 선택한다.
- 수는 3자리 숫자이고, 랜덤으로 정해진다.
- 정답을 맞출 때 까지 반복한다.
- 컴퓨터는 입력한 숫자에 대한 결과를 출력한다.
- 컴퓨터수와 사용자의 수를 비교해 위치는 틀리지만 수가 맞으면 볼을 출력
- 컴퓨터수와 사용자의 수를 비교해 위치도 맞고 수가 맞으면 스트라이크를 출력
- 컴퓨터수와 사용자의 수를 비교해 위치도, 수도 맞은게 없다면 낫싱을 출력
- 사용자가 수를 입력할 수 있다.
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생 후 종료
- 컴퓨터의 수를 맞추면 게임 종료. 종료 후 한번 더 할지, 끝낼지 입력받는다.

# 역할을 나눈다.

## 답을 생성하는 역할
- 컴퓨터가 수를 선택한다.
- 수는 서로 다른 3자리 숫자이고, 랜덤으로 정해진다.

## 정답을 입력을 할 수 있는 역할
- 사용자가 수를 입력할 수 있다.
- 수는 서로 다른 3자리 숫자이다. (검증필요)
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생 후 종료

## 정답이 맞는지 판단하고 힌트를 주는 역할
- 컴퓨터수와 사용자의 수를 비교해 위치는 틀리지만 수가 맞으면 볼을 출력
- 컴퓨터수와 사용자의 수를 비교해 위치도 맞고 수가 맞으면 스트라이크를 출력
- 컴퓨터수와 사용자의 수를 비교해 위치도, 수도 맞은게 없다면 낫싱을 출력

## 게임을 제어하는 역할
- 정답을 맞출 때 까지 반복한다.
- 정답을 맞추면 게임 종료.
- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다. 종료 후 한번 더 할지, 끝낼지 입력받는다.
5 changes: 3 additions & 2 deletions src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package baseball;

public class Application {

public static void main(String[] args) {
// TODO: 프로그램 구현
GameLauncher launcher = new NumberBaseBallGameLauncher();
launcher.startGame();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사소한 거긴한데 GameLauncher가 start란 메소드를 사용하는 경우는 게임이 시작되는 경우니까 메소드 명에서 Game이란 단어를 빼도 좋을거 같네요(꼭 따를 필요는 없지만 클린코드 지침에도 중복된 단어 사용에 관한 내용이 있습니다. 학습하면 좋을거 같네요)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네! 이런 도메인의 코드를 짜보지 않아서 생각하지못하고 짰네요! 감사합니다!

}
}
20 changes: 20 additions & 0 deletions src/main/java/baseball/Computer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package baseball;

import java.util.HashSet;
import java.util.Set;

import static camp.nextstep.edu.missionutils.Randoms.pickNumberInRange;

public class Computer {
public String createGameValue() {
// 컴퓨터 수 생성
Set<Integer> targetSet = new HashSet<>();
while (targetSet.size() < 3) {
targetSet.add(pickNumberInRange(1, 9));
}

return targetSet.stream()
.map(String::valueOf)
.reduce("", String::concat);
}
}
93 changes: 93 additions & 0 deletions src/main/java/baseball/GameInputValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package baseball;

import baseball.enums.ExceptionMessage;
import baseball.exception.WrongInputException;

import java.util.HashSet;

public class GameInputValue {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

의도가 불분명한 클래스인거 같아요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞습니다..

private String userInputValue;
private final String computerValue;

public GameInputValue(String computerValue) {
this.computerValue = computerValue;
this.userInputValue = "";
}

public String getUserInputValue() {
return userInputValue;
}

public String getComputerValue() {
return computerValue;
}

// TODO 조금 더 명확한 목적을 띄는 메서드 ...
public void setUserInputValue(String userInputValue) {
this.userInputValue = userInputValue;
checkValidUserInput();
}

public boolean isEqaulsUserAndComputerValue() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뭔가 행동을 보면 Judgement와 비슷한거 같은데 역할이 중복되는거 같아요

return this.userInputValue.equals(this.computerValue);
}

public int countSameNumber() {
int count = 0;
for (char c : this.userInputValue.toCharArray()) {
if (this.computerValue.contains(String.valueOf(c))) {
count++;
}
}
return count;
}

public int countSamePositionAndNumber(){
int count = 0;
char[] computerValueCharArr = computerValue.toCharArray();
char[] userVauleCharArr = userInputValue.toCharArray();
for (int i = 0; i < computerValueCharArr.length; i++) {
if (computerValueCharArr[i] == userVauleCharArr[i]) {
count++;
}
}
return count;
}

public boolean isDuplicationNumberInUserInputValue() {
HashSet<Character> set = new HashSet<>();
for (char c : this.userInputValue.toCharArray()) {
set.add(c);
}
return set.size() != 3;
}

public boolean isNothing() {
return countSameNumber() == 0;
}


public void checkValidUserInput() {
if (!isThreeDigits()) {
throw new WrongInputException(ExceptionMessage.WRONG_INPUT_NOT_THREE_DIGITS.getMessage());
}

if (!isNumber()){
throw new WrongInputException(ExceptionMessage.WRONG_INPUT_NOT_NUMBER.getMessage());
}

if(isDuplicationNumberInUserInputValue()){
throw new WrongInputException(ExceptionMessage.WRONG_INPUT_DUPLICATE_VALUE.getMessage());
}
}


private boolean isThreeDigits() {
return userInputValue.length() == 3;
}

private boolean isNumber() {
return userInputValue != null && userInputValue.matches("[-+]?\\d*\\.?\\d+");
}

}
11 changes: 11 additions & 0 deletions src/main/java/baseball/GameLauncher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package baseball;

public interface GameLauncher{
void startGame();

void initGame();

void endGame();

void play(GameInputValue value); //TODO 확장성이 아쉬운 느낌 ..?
}
17 changes: 17 additions & 0 deletions src/main/java/baseball/Judgement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package baseball;

import baseball.enums.GameProgressMessage;

public class Judgement {

public void judge(GameInputValue gameValue) {
// 사용자 수와 컴퓨터 수 비교 => 판정하는 클래스가 해야할 일
Result result = new Result(gameValue.countSameNumber() - gameValue.countSamePositionAndNumber(), gameValue.countSamePositionAndNumber());
if (gameValue.isNothing()) {
PrintMessage.printlnMessage(GameProgressMessage.NOTHING);
} else {
PrintMessage.printlnMessage(GameProgressMessage.makeHintMessage(result));
}
}

}
73 changes: 73 additions & 0 deletions src/main/java/baseball/NumberBaseBallGameLauncher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package baseball;

import baseball.enums.GameFlag;
import baseball.enums.GameProgressMessage;
import baseball.enums.OrNot;

import static camp.nextstep.edu.missionutils.Console.readLine;
public class NumberBaseBallGameLauncher implements GameLauncher{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

게임런처를 인터페이스로 선언했다는 건 확장성이 있다는 것으로 인식했습니다. 예를 들어 게임런처의 내부 동작이 다른 동작이나 구현을 사용하게 된다던지? 그렇게 되면 객체제향의 OCP를 위반하지 않고 기존 구현체의 수정 없이 새로운 구현체를 만들게 되겠죠? NumberBaseBall이라고 만들었는데,NumberBaseBall이란게 위의 설명에 부합한 이름은 아닌거 같네요. 숫자야구게임에 숫자가 안쓰이고 다른게 쓰일 수 있을까요? 구현체에 걸맞는 이름이 필요해보여요

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

생각하지 못했던거 같습니다 앞으로 이름을 신중하게 지어야겠네요!


private GameFlag flag = GameFlag.START;
private Computer computer = new Computer();
private Judgement judgement = new Judgement();

@Override
public void startGame() {
PrintMessage.printlnMessage(GameProgressMessage.START);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MVC 패턴에 관한 학습이 필요할거 같아요. 게임 실행 클래스가 메시지에 의존하고 있는데 이렇게되면 뷰의 구현체가 달라지거나 메서드가 삭제될 경우 게임런처 구현체에도 그 영향이 전달됩니다. 즉, 단일책임원칙 위배에요...!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네! 생각해서 다시 리팩토링하겠습니다!

initGame();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인터페이스의 역할에 관해 고민해보는게 좋을거 같아요! 인터페이스를 사용할 때는 객체 사이의 메시지를 주고 받을 때일텐데, 여기서 init메서드가 play 메서드 안으로 들어가면 인터페이스로 선언하는게 의미가 있을까 싶네요. 인터페이스를 왜 사용하는지 그렇다면 추상클래스랑은 어떤 차이가 있고 어떤 상황에서 둘을 사용할지 공부해보세요~

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 감사합니다!

}

@Override
public void initGame() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Init에서 시작해서 계속 메서드를 내부에서 호출하고 있는데 이러면 다른 메서드를 public으로 만든게 의미가 없지 않을까요?🧐 내부에서만 사용할 메서드는 private로 만들어 캡슐화 하는게 더 좋잖아요

if(flag == GameFlag.START){
GameInputValue gameValue = new GameInputValue(computer.createGameValue());
flag = GameFlag.ING;
play(gameValue);
}

}

@Override
public void endGame() {}

@Override
public void play(GameInputValue gameValue) {
if (flag == GameFlag.ING) {
PrintMessage.printMessage(GameProgressMessage.INPUT_NUMBER);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

내부 로직이 뷰에 의존하고 있어요!

gameValue.setUserInputValue(readLine());
judgement.judge(gameValue);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Judgement라는 클래스는 의미있지만, 객체 사이에 메시지를 주고 받고 있지 않네요. 객체지향적이지 못한 코드라고 생각해요


// 리플레이 또는 종료
if(isWin(gameValue)){
PrintMessage.printlnMessage(GameProgressMessage.PLAY_NEXT_GAME_OR_NOT);
replayOrEnd();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안에서 flag의 상태를 바꾸고 있는건가요? 일단 메서드가 내부 상태를 변경하는 것과 질의하는 것의 차이를 알필요가 있어요! 이것도 객체지향에 관한 필수적인 이해입니다. 그리고 flag라는 네이밍이 너무 모호해요


if (flag == GameFlag.START) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

분기처리가 자연스럽지 않아요. 그리고 퍼블릭으로 만든 메서드인데 모두 내부에서만 쓰이고 있네! 공개할 메서드(인터페이스)와 내부 메서드를 구분할 필요가 있어요

initGame();
}

if (flag == GameFlag.END) {
endGame();
}

return;
}
play(gameValue);
}
}

public boolean isWin(GameInputValue gameValue) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 전체적으로 구현한 코드를 봤을 때 승리를 판단하는 메서드는 gameLauncher의 책임이 아닌거 같아요

return gameValue.isEqaulsUserAndComputerValue();
}

public void replayOrEnd() {
String answer = readLine();
if (answer.equals(OrNot.YES.getProcessCode())) {
flag = GameFlag.START;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

게임 시작, 재시작에 관한 정보를 런처클래스가 필드에 갖고 있을 필요는 없을거 같아요. 그리고 클래스의 상태정보를 변경할거라면 메서드에 좀 더 적절한 네이밍이 필요할거 같네요

}
if (answer.equals(OrNot.NO.getProcessCode())) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enum 클래스도 클래스이기 때문에 역할과 책임이 있습니다 이를 고려하먼 좀 더 괜찮은 방식으로 로직을 짤 수 있을거 같아요

flag = GameFlag.END;
}
}

}
22 changes: 22 additions & 0 deletions src/main/java/baseball/PrintMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package baseball;

import baseball.enums.GameProgressMessage;

public class PrintMessage {

public static void printlnMessage(GameProgressMessage gameProgressMessage) {
System.out.println(gameProgressMessage.getKorMessage());
}

public static void printMessage(GameProgressMessage gameProgressMessage) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고정된 메시지 출력에 관한 데이터는 뷰 클래스가 가지고 있는게 좋지 않을까요? 뷰는 변하는 데이터를 잘 반영하면 되고 나머지는 안변하니까요

System.out.print(gameProgressMessage.getKorMessage());
}

public static void printMessage(String message) {
System.out.print(message);
}

public static void printlnMessage(String message) {
System.out.println(message);
}
}
Loading