Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
fcbf2e3
feat: 게임 실행 로직에서 타입 확인 제거 개선
Libienz Mar 27, 2024
72d8cf8
feat: 보드의 책임과 체스보드의 검증 책임 분리
Libienz Mar 27, 2024
c3cae93
test: 체스 게임 도메인 턴 개념 테스트 추가
Libienz Mar 27, 2024
61d679f
test: 불필요한 static import 제거, 테스트 가독성 향상 개선
Libienz Mar 27, 2024
ce8bffc
refactor: 불필요한 주석 제거 개선
Libienz Mar 27, 2024
7b5c587
test: Piece 기물 공통 로직 누락된 테스트 추가 구현
Libienz Mar 27, 2024
60e59aa
refactor: 의미 있는 매직 넘버 상수화 개선
Libienz Mar 27, 2024
7367eb1
fix: 명령어 변환 과정 견고화 및 테스트 추가
Libienz Mar 27, 2024
40c5e33
docs: 3단계 기능 요구사항 작성
Libienz Mar 27, 2024
6d24abb
docs: 기능 요구사항 간략화 개선
Libienz Mar 27, 2024
7afc4bc
feat: Score 객체 속성 정의 및 구현
Libienz Mar 27, 2024
270f24e
feat: 각 기물별 점수 다형성 통해서 정의
Libienz Mar 27, 2024
43a09ac
test: 도메인 추상 메서드 추가로 인한 테스트 수정
Libienz Mar 27, 2024
013ac29
feat: 점수끼리 더하는 기능 구현
Libienz Mar 27, 2024
e185bf1
fix: 점수 가져오는 메서드 접근 제어자 수정
Libienz Mar 27, 2024
243e8b0
feat: Score 객체 동등성 및 해시 재정의
Libienz Mar 27, 2024
0cdc887
feat: 체스보드에서 팀의 기본점수 합을 계산하는 기능 구현
Libienz Mar 27, 2024
47f2d6a
feat: 폰인지 확인할 수 있는 추상 메서드 설정 및 구현
Libienz Mar 27, 2024
ebe16a8
test: 추상 메서드 추가에 따른 테스트 코드 수정
Libienz Mar 27, 2024
16826b3
feat: 특정 팀이 주어졌을 때 같은 파일에 있는 폰의 개수를 세는 기능 추가
Libienz Mar 27, 2024
fd7f007
refactor: 메서드 분리 및 스트림활용 선언형으로 개선
Libienz Mar 27, 2024
1929dc1
style: 공백 컨벤션 개선
Libienz Mar 27, 2024
cc66773
feat: 점수끼리 곱셈할 수 있는 기능 구현
Libienz Mar 27, 2024
5d549ce
feat: 체스 게임 도메인에서 각 팀의 점수를 계산할 수 있는 기능 구현
Libienz Mar 27, 2024
78ad985
feat: status 출력 뷰로직 구현
Libienz Mar 27, 2024
8781657
feat: status 커맨드 구현
Libienz Mar 27, 2024
2a01371
feat: 입력 뷰로직에 새로운 명령어 추가 구현
Libienz Mar 27, 2024
ca9b473
fix: double 타입을 formatting할 때 서식지정자 문법에 맞게 수정
Libienz Mar 27, 2024
21df77e
feat: 점수간 비교 기능 구현
Libienz Mar 27, 2024
6bd2cd1
feat: 이긴 진영을 계산 및 출력하는 기능 추가 구현
Libienz Mar 27, 2024
03702e7
fix: String format 인자 넘겨주지 않던 오류 해결
Libienz Mar 27, 2024
5a49e74
docs: 기능 구현 목록 최신화
Libienz Mar 27, 2024
2e9fabc
feat: 특정 기물이 킹인지 확인하는 기능 구현
Libienz Mar 27, 2024
ed7939e
feat: 킹이 잡히면 게임이 종료되는 기능 구현
Libienz Mar 27, 2024
df94333
docs: 4단계 기능 요구사항 작성
Libienz Mar 28, 2024
5219281
test: 테스트에 불필요한 익명 클래스 정의 부분 제거
Libienz Mar 28, 2024
92e8d10
chore: DB 설정
Libienz Mar 28, 2024
c079e96
feat: Connection 가져오는 관리 클래스 구현
Libienz Mar 28, 2024
e6f0d07
feat: 기물 정보 게터 프로퍼티 추가
Libienz Mar 29, 2024
6c386fd
feat: ChessGame 턴 게터 추가
Libienz Mar 29, 2024
74108b0
feat: 턴을 조작하는 체스게임 생성자 추가 구현
Libienz Mar 29, 2024
fb2c817
feat: 피스 배치 정보 전달 객체 구현
Libienz Mar 29, 2024
9f787d6
feat: 도메인 <-> DB value 변환 매퍼 구현
Libienz Mar 29, 2024
30d43b5
feat: 기물 배치 정보 저장소 dao 구현
Libienz Mar 29, 2024
dcda05d
feat: 턴 정보 저장 기능 구현
Libienz Mar 29, 2024
09fec55
feat: 체스게임 저장 및 로드 기능 구현
Libienz Mar 29, 2024
3b201cf
feat: 체스보드 맵 게터 프로퍼티 구현
Libienz Mar 29, 2024
8ba88ff
refactor: 영속성 레이어 try with resources를 활용하여 예외를 처리하도록 개선
Libienz Mar 29, 2024
f39f6f1
refactor: 영속화 레이어 옵셔널 사용하도록 변경
Libienz Mar 29, 2024
54e348d
feat: DB 저장 기능 구현
Libienz Mar 29, 2024
20cf64f
fix: 턴을 db에서 가져올 때 잘못 가져오는 현상 수정
Libienz Mar 29, 2024
75d9ebc
feat: 테이블 스키마 추가
Libienz Mar 29, 2024
f3be8e8
refactor: 진행중인 게임이 있는 경우와 아닌 경우의 분기를 컨트롤러가 모르도록 개선
Libienz Mar 31, 2024
44b50b6
refactor: 사용하지 않는 메서드 제거 개선
Libienz Mar 31, 2024
65af47f
feat: 점수 현황 DTO 구현
Libienz Mar 31, 2024
083ca2e
refactor: 컨트롤러가 서비스 레이어만 의존하도록 개선
Libienz Mar 31, 2024
4e19ad8
refactor: 게임 종료 여부를 서비스에 묻도록 개선
Libienz Mar 31, 2024
3cfa820
feat: 새로운 체스 게임 생성 로직 체스 게임 도메인 로직으로 응집
Libienz Mar 31, 2024
2db4eb5
refactor: 메서드 배치 개선
Libienz Mar 31, 2024
c861063
refactor: 조건문 simplify 개선
Libienz Mar 31, 2024
d9dfcb2
feat: File의 열 번호 게터 추가
Libienz Mar 31, 2024
3fe6cf2
feat: BoardSnapShotDto 구현
Libienz Mar 31, 2024
1e26dc3
feat: 보드 상태 스냅샷 DTO 구현
Libienz Mar 31, 2024
f960aba
feat: 스냅샷 기반 체스 보드 출력 기능 추가
Libienz Mar 31, 2024
de67de5
refactor: 서비스 레이어가 DTO를 반환하여 결과를 참조할 수 있도록 개선
Libienz Mar 31, 2024
5462f0c
refactor: 뷰로직 사용하지 않는 메서드 제거 개선 및 배치 개선
Libienz Mar 31, 2024
661203a
rename: DTO 클래스 이름 수정
Libienz Mar 31, 2024
21b7459
refactor: 여러개의 기물 저장시 하나의 커넥션 이용하도록 개선
Libienz Mar 31, 2024
a6d4aff
rename: DTO 클래스명 변경
Libienz Mar 31, 2024
02ebd2b
refactor: DTO 일급 컬렉션 추가 구현 및 생성 로직 응집 개선
Libienz Mar 31, 2024
f2b0d15
refactor: 메서드 인라인 개선
Libienz Mar 31, 2024
9c32053
refactor: DTO일급 컬렉션을 사용하도록 수정
Libienz Mar 31, 2024
66ac4b2
test: 점수 계산 로직 테스트 추가
Libienz Mar 31, 2024
059b37b
refactor: 체스 게임 점수 비교 로직 체스게임 도메인안으로 응집 개선
Libienz Mar 31, 2024
84a4043
test: 점수 비교 테스트 작성
Libienz Mar 31, 2024
7c2e131
refactor: 사용하지 않는 메서드 제거 개선
Libienz Mar 31, 2024
0b5b6ec
refactor: 예외 상황 발생 시 확실히 처리하도록 개선
Libienz Mar 31, 2024
6cb54fe
refactor: 미사용 변수 제거 개선
Libienz Mar 31, 2024
27c723b
chore: 테스트 목 라이브러리 의존성 추가
Libienz Apr 1, 2024
8e978c4
test: 서비스 레이어 테스트 추가
Libienz Apr 1, 2024
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
126 changes: 70 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,84 @@
# java-chess

## 체스 게임 설명
### 입력 요구사항

- 체스 게임은 화이트 팀과 블랙 팀으로 나뉜다
- 체스 게임이 시작되면 화이트 팀부터 한 수씩 턴이 진행된다
- [x] 체스 게임을 시작하는 명령어를 입력받을 수 있다.
- [x] 체스 게임을 종료하는 명령어를 입력받을 수 있다.
- [x] 체스 말을 이동하는 명령어를 입력받을 수 있다.
- [x] 각 진영의 점수를 확인하는 명령어를 입력받을 수 있다.
- [x] 명령어 입력시 형식에 맞는 입력이 들어오지 않으면 예외를 발생시킨다.

## 1-2단계 요구사항
### 출력 요구사항

콘솔 UI에서 체스 게임을 할 수 있는 기능을 구현한다.
1단계는 체스 게임을 할 수 있는 체스판을 초기화한다.
체스판에서 말의 위치 값은 가로 위치는 왼쪽부터 a ~ h이고, 세로는 아래부터 위로 1 ~ 8로 구현한다.
- [x] 체스판의 초기 상태를 출력할 수 있다
- [x] 매 턴마다 최신화된 체스판의 상태를 출력할 수 있다
- [x] 체스판에서 각 진영은 대문자(검은색)와 소문자(흰색)로 출력한다.

### 입력 요구사항
### 도메인 요구사항

#### 기물

- [x] 기물들은 화이트 또는 블랙의 팀을 가진다.
- [x] 기물들은 각각의 행마법에 따라 이동할 수 있다

```
- 룩은 직선으로 이동할 수 있다
- 비숍은 대각선으로 이동할 수 있다
- 퀸은 직선/대각선으로 이동할 수 있다
- 룩과 비숍, 퀸은 이동하는 경로에 기물이 존재하면 이동할 수 없다.
- 킹은 방향과 무관하게 1칸 이동할 수 있다
- 나이트는 알파벳 L자 모양으로 앞으로 두칸 이동한 다음 왼쪽, 오른쪽 으로 한칸 움직일 수 있다
- 폰은 초기 상태에서 한칸 또는 두칸씩 전진할 수 있다
- 폰은 초기 상태에서 움직인 이후에는 한칸씩만 전진할 수 있다
- 폰은 상대 기물이 한칸 대각선에 있다면, 이동할 수 있다
- 모든 기물은 도착지에 같은 팀의 기물이 있다면 이동할 수 없다
```

#### 체스 보드 초기화

- [x] 체스 게임을 시작할지 여부를 입력받을 수 있다.
- [x] 체스 게임을 종료할지 여부를 입력받을 수 있다.
- [x] 체스 말의 이동정보를 입력받을 수 있다
- [x] 게임 시작시 체스판을 초기화할 수 있다.
- [x] 체스판의 초기상태는 다음과 같다.
```
move b2 b3
RNBQKBNR
PPPPPPPP
........
........
........
........
pppppppp
rnbqkbnr
```
- [x] 요구하는 형식의 입력이 들어오지 않으면 예외를 발생시킨다.
- [x] 체스판의 열은 왼쪽부터 a-h까지의 알파벳으로 이루어져 있다.
- [x] 체스판의 행은 밑부터 1-8까지의 숫자로 이루어져 있다.

### 출력 요구사항
#### 체스 보드

- [x] 체스판의 상태를 출력할 수 있다.
- [x] 체스판의 초기 상태를 출력할 수 있다
- [x] 매 턴마다 최신화된 체스판의 상태를 출력할 수 있다
- [x] 체스판에서 각 진영은 대문자(검은색)와 소문자(흰색)로 출력한다.
- [x] 체스보드 상태를 업데이트 할 수 있다
- [x] 기물들의 행마법을 검증할 수 있다
- [x] 기물들을 이동시킬 수 있다.
- [x] 기물들의 위치는 체스보드 범위를 벗어날 수 없다.
- [x] 기물들이 이동할 수 없다면 기물의 위치를 옮기지 않는다

### 도메인 요구사항
#### 체스 게임

- [x] 체스 게임은 백팀의 이동으로 시작해야 한다.
- [x] 기물의 움직임 마다 자신의 턴인지 검증할 수 있어야 한다.
- [ ] 킹이 잡힌 경우 게임을 끝낼 수 있어야 한다.

#### 점수 계산

- [x] 체스 프로그램에서 현재까지 남아 있는 말에 따라 점수를 계산할 수 있어야 한다.

```
Queen은 9점
Rook은 5점
Bishop은 3점
Knight는 2.5점
Pawn의 기본 점수는 1점, 같은 세로줄에 같은 색의 폰이 있는 경우는 0.5점으로 계산
King은 점수가 없음 (잡히는 경우 게임 끝)
```

#### 이어 하기

- [x] 체스 보드 초기화
- [x] 게임 시작시 체스판을 초기화할 수 있다.
- [x] 체스판의 초기상태는 다음과 같다.
```
RNBQKBNR
PPPPPPPP
........
........
........
........
pppppppp
rnbqkbnr
```
- [x] 체스판의 열은 왼쪽부터 a-h까지의 알파벳으로 이루어져 있다.
- [x] 체스판의 행은 밑부터 1-8까지의 숫자로 이루어져 있다.
- [x] 기물들은 화이트 또는 블랙의 색깔을 가진다.

- [x] 기물 이동
- [x] 기물들의 위치는 체스보드 범위를 벗어날 수 없다.
- [x] 기물들은 각자의 행마법을 따라 이동할 수 있다
- [x] 룩은 직선으로 이동할 수 있다
- [x] 비숍은 대각선으로 이동할 수 있다
- [x] 퀸은 직선/대각선으로 이동할 수 있다
- [x] 킹은 방향과 무관하게 1칸 이동할 수 있다
- [x] 나이트는 알파벳 L자 모양으로 앞으로 두칸 이동한 다음 왼쪽, 오른쪽 으로 한칸 움직일 수 있다
- [x] 폰의 행마법
- [x] 폰은 초기 상태에서 한칸 또는 두칸씩 전진할 수 있다
- [x] 폰은 초기 상태에서 움직인 이후에는 한칸씩만 전진할 수 있다
- [x] 상대 기물이 한칸 대각선에 있다면, 이동할 수 있다

- [x] 체스 보드
- [x] 체스보드 상태를 업데이트 할 수 있다
- [x] 기물들이 이동할 수 있다면 기물의 위치를 옮긴다
- [x] 기물들이 이동할 수 없다면 기물의 위치를 옮기지 않는다
- [x] 도착지에 같은 팀의 기물이 있다면 이동할 수 없다
- [x] 비숍/룩/퀸은 이동 경로에 다른 기물이 있다면 이동할 수 없다

- [ ] 애플리케이션을 재시작하더라도 이전에 하던 체스 게임을 다시 시작할 수 있어야 한다.

3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
testImplementation 'org.mockito:mockito-core:3.6.28'

runtimeOnly("com.mysql:mysql-connector-j:8.3.0")
}

java {
Expand Down
18 changes: 18 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: "3.9"
services:
db:
image: mysql:8.0.28
platform: linux/x86_64
restart: always
ports:
- "13306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: chess
MYSQL_USER: user
MYSQL_PASSWORD: password
TZ: Asia/Seoul
volumes:
- ./db/mysql/data:/var/lib/mysql
- ./db/mysql/config:/etc/mysql/conf.d
- ./db/mysql/init:/docker-entrypoint-initdb.d
9 changes: 8 additions & 1 deletion src/main/java/chess/ChessApplication.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package chess;

import chess.controller.ChessGameController;
import chess.repository.ConnectionManager;
import chess.repository.PieceRepository;
import chess.repository.TurnRepository;
import chess.service.ChessGameService;
import chess.view.CommandParser;
import chess.view.InputView;
import chess.view.OutputView;
Expand All @@ -9,8 +13,11 @@ public class ChessApplication {
public static void main(String[] args) {
InputView inputView = new InputView(new CommandParser());
OutputView outputView = new OutputView();
PieceRepository pieceRepository = new PieceRepository(new ConnectionManager());
TurnRepository turnRepository = new TurnRepository(new ConnectionManager());
ChessGameService chessGameService = new ChessGameService(pieceRepository, turnRepository);

ChessGameController controller = new ChessGameController(inputView, outputView);
ChessGameController controller = new ChessGameController(inputView, outputView, chessGameService);
controller.run();
}
}
29 changes: 11 additions & 18 deletions src/main/java/chess/controller/ChessGameController.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
package chess.controller;

import chess.controller.command.Command;
import chess.domain.ChessGame;
import chess.domain.board.ChessBoard;
import chess.domain.board.ChessBoardCreator;
import chess.controller.command.ExecuteResult;
import chess.service.ChessGameService;
import chess.view.InputView;
import chess.view.OutputView;

public class ChessGameController {
private final InputView inputView;
private final OutputView outputView;
private final ChessGameService chessGameService;
Comment on lines 10 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

나도 Service를 이용했는데, 이 부분에서 필드를 세 개 사용한다는 지적을 받았어.
어떻게 이야기 해야 될까?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

나도 어떻게 해야 할지 속으로만 생각했는데 컨트롤러를 호출하는 Application 클래스를 요청자로써 새로 정의할 것 같아

Application을 요청자로 정의하여 InputView와 OutputView를 할당하고 Application이 컨트롤러에 요청할 때는 입력받은 String 혹은 Command로 요청하도록 하는 거지.

이렇게 하면 컨트롤러는 들어오는 요청과 요청을 위임할 서비스 레이어만 알게되고 어플리케이션 클래스가 InputView와 OutputView를 아는 요청자가 된다는 측면에서 하나의 해결책이 될 수 있지 않을까 생각함 👍


public ChessGameController(InputView inputView, OutputView outputView) {
public ChessGameController(InputView inputView, OutputView outputView, ChessGameService chessGameService) {
this.inputView = inputView;
this.outputView = outputView;
this.chessGameService = chessGameService;
}

public void run() {
outputView.printStartMessage();
Command command = inputView.readCommand();
if (command.isNotStartCommand()) {
return;
}
chessGameService.startChessGame();

ChessGame chessGame = initializeChessGame();
while (command.isNotEndCommand()) {
command.execute(chessGame, outputView);
command = inputView.readCommand();
ExecuteResult result;
do {
Command command = inputView.readCommand();
result = command.execute(chessGameService, outputView);
}
}

private ChessGame initializeChessGame() {
ChessBoardCreator chessBoardCreator = new ChessBoardCreator();
ChessBoard chessBoard = chessBoardCreator.create();
return new ChessGame(chessBoard);
while (result.isSuccess() && result.isNeedNextCommand() && chessGameService.isChessGameNotEnd());
}
}
8 changes: 2 additions & 6 deletions src/main/java/chess/controller/command/Command.java
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Controller의 역할 일부를 Command로 분리한 부분이 인상깊네요!

Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package chess.controller.command;

import chess.domain.ChessGame;
import chess.service.ChessGameService;
import chess.view.OutputView;

public interface Command {
void execute(ChessGame chessGame, OutputView outputView);

boolean isNotEndCommand();

boolean isNotStartCommand();
ExecuteResult execute(ChessGameService chessGameService, OutputView outputView);
}
15 changes: 3 additions & 12 deletions src/main/java/chess/controller/command/EndCommand.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
package chess.controller.command;

import chess.domain.ChessGame;
import chess.service.ChessGameService;
import chess.view.OutputView;

public class EndCommand implements Command {
@Override
public void execute(ChessGame chessGame, OutputView outputView) {
}

@Override
public boolean isNotEndCommand() {
return false;
}

@Override
public boolean isNotStartCommand() {
return true;
public ExecuteResult execute(ChessGameService chessGameService, OutputView outputView) {
return new ExecuteResult(true, false);
}
}
19 changes: 19 additions & 0 deletions src/main/java/chess/controller/command/ExecuteResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package chess.controller.command;

public class ExecuteResult {
private final boolean success;
private final boolean needNextCommand;

public ExecuteResult(boolean success, boolean needNextCommand) {
this.success = success;
this.needNextCommand = needNextCommand;
}
Comment on lines +7 to +10
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

boolean 타입 변수 두개가 연속으로 나와서, 아주 헷갈릴 것 같아요. 래핑 하는 것이 나을 것 같아요.


public boolean isSuccess() {
return success;
}

public boolean isNeedNextCommand() {
return needNextCommand;
}
}
20 changes: 6 additions & 14 deletions src/main/java/chess/controller/command/MoveCommand.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package chess.controller.command;

import chess.domain.ChessGame;
import chess.domain.position.Position;
import chess.dto.BoardDto;
import chess.service.ChessGameService;
import chess.view.OutputView;

public class MoveCommand implements Command {
Expand All @@ -14,18 +15,9 @@ public MoveCommand(Position start, Position destination) {
}

@Override
public void execute(ChessGame chessGame, OutputView outputView) {
chessGame.move(start, destination);
outputView.printChessBoardMessage(chessGame.getChessBoard());
}

@Override
public boolean isNotEndCommand() {
return true;
}

@Override
public boolean isNotStartCommand() {
return true;
public ExecuteResult execute(ChessGameService chessGameService, OutputView outputView) {
BoardDto boardDto = chessGameService.movePiece(start, destination);
outputView.printChessBoardMessage(boardDto);
return new ExecuteResult(true, true);
}
}
19 changes: 6 additions & 13 deletions src/main/java/chess/controller/command/StartCommand.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
package chess.controller.command;

import chess.domain.ChessGame;
import chess.dto.BoardDto;
import chess.service.ChessGameService;
import chess.view.OutputView;

public class StartCommand implements Command {
@Override
public void execute(ChessGame chessGame, OutputView outputView) {
outputView.printChessBoardMessage(chessGame.getChessBoard());
}

@Override
public boolean isNotEndCommand() {
return true;
}

@Override
public boolean isNotStartCommand() {
return false;
public ExecuteResult execute(ChessGameService chessGameService, OutputView outputView) {
BoardDto boardDto = chessGameService.startChessGame();
outputView.printChessBoardMessage(boardDto);
return new ExecuteResult(true, true);
}
}
15 changes: 15 additions & 0 deletions src/main/java/chess/controller/command/StatusCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package chess.controller.command;

import chess.dto.ScoreStatusDto;
import chess.service.ChessGameService;
import chess.view.OutputView;

public class StatusCommand implements Command {

@Override
public ExecuteResult execute(ChessGameService chessGameService, OutputView outputView) {
ScoreStatusDto scoreStatusDto = chessGameService.calculateScoreStatus();
outputView.printStatusMessage(scoreStatusDto);
return new ExecuteResult(true, true);
}
}
Comment on lines +7 to +15
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

나도 이런 형식의 Command 도입을 고려했었는데 각 커멘드마다 로직이 여러 파일로 분리되는 것 같아 꺼려했었어
리비는 일종의 상태 패턴을 도입했을 때, 어떤 장점을 얻었어?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

나만의 커맨드 패턴에 대한 소감있지 ㅋㅋ

우선 나는 만약에 그냥 명령의 타입만 확인하고 컨트롤러 코드에서 다음과 같이 분기한다면 그건 책임이 잘못된 것이라고 생각해.

// 컨트롤러 내부 코드
if(command == Command.START) {
    // do someting
}
if(command == Command.END) {
    // do someting
}
if(command == Command.STATUS) {
    // do someting
}
if(command == Command.MOVE) {
    // do someting
}

명령이라는 도메인을 정의했을 때는 응당 해당 명령에 대한 동작을 응집할 수 있어야 한다고 생각했어
그리고 이러한 것을 가능하게 한 것이 커맨드 패턴이었네
커맨드 패턴을 통해서 결국 기능 배치에 있어서 책임에 위화감 없는 개선 할 수 있었다고 생각함 👍

Loading