-
Notifications
You must be signed in to change notification settings - Fork 0
[체스 - 3, 4 단계] 재즈(함석명) 미션 제출합니다. #18
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
base: seokmyungham
Are you sure you want to change the base?
Changes from all commits
5eec398
44befb2
67070ed
42cfa33
3cf2780
2cb887d
5c47f78
972d9d8
19d005c
e495e9e
5062766
0777b71
b4ce577
ba433da
d144ce7
3d97e2d
c9d5677
6ba1c2d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package chess; | ||
|
|
||
| import chess.controller.ChessGameController; | ||
| import chess.repository.BoardRepository; | ||
| import chess.repository.BoardRepositoryImpl; | ||
| import chess.repository.RoomRepository; | ||
| import chess.repository.RoomRepositoryImpl; | ||
| import chess.service.BoardService; | ||
| import chess.service.GameService; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| RoomRepository roomRepository = new RoomRepositoryImpl(); | ||
| BoardRepository boardRepository = new BoardRepositoryImpl(); | ||
|
|
||
| GameService gameService = new GameService(roomRepository, boardRepository); | ||
| BoardService boardService = new BoardService(roomRepository, boardRepository); | ||
| ChessGameController chessGameController = new ChessGameController(gameService, boardService); | ||
| chessGameController.run(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package chess.controller; | ||
|
|
||
| import chess.controller.command.Command; | ||
| import chess.controller.command.CommandRouter; | ||
| import chess.domain.game.Room; | ||
| import chess.service.BoardService; | ||
| import chess.service.GameService; | ||
| import chess.view.InputView; | ||
| import chess.view.OutputView; | ||
|
|
||
| public class ChessGameController { | ||
|
|
||
| private final GameService gameService; | ||
| private final BoardService boardService; | ||
|
|
||
| public ChessGameController(GameService gameService, BoardService boardService) { | ||
| this.gameService = gameService; | ||
| this.boardService = boardService; | ||
| } | ||
|
|
||
| public void run() { | ||
| OutputView.printRoomNames(gameService.findAllRoomNames()); | ||
| Room room = createRoom(); | ||
| OutputView.printStartMessage(room.getName()); | ||
| process(gameService, boardService, room.getId()); | ||
| } | ||
|
|
||
| private Room createRoom() { | ||
| try { | ||
| String input = InputView.readRoomName(); | ||
| return gameService.loadRoom(input); | ||
| } catch (RuntimeException error) { | ||
| OutputView.printError(error); | ||
| return createRoom(); | ||
| } | ||
| } | ||
|
Comment on lines
+28
to
+36
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사실 코드를 처음보는 입장에서 가장 먼저 하게 되는 일은 메서드 시그니처를 읽고 해당 메서드가 어떤 일을 하는지 예측하는 것인 것 같아. (적어도 나는 ㅋㅋ) 현재 createRoom()이라는 메서드 만 보았을 때는 Room을 하나 만들겠구나 예상 되는 데 안의 동작을 보면 서비스에서 게임을 로드하는 것으로 보여 좋은 시그니처가 가독성 좋은 코드로 이어진다고 믿는 사람으로써 재즈도 이러한 부분을 무게감 있게 생각해보면 좋을 것 같음! 👍
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헉 맞아.. 내 pr 가서 읽어보면 아마 웃음이 나올 수도.. 레디 리뷰에 시그니처 관련 리뷰를 잔뜩 달아놓고 정작 내가 더 문제가 심각한듯,, 반성중이야.. |
||
|
|
||
| private void process(GameService gameService, BoardService boardService, Long roomId) { | ||
| State state = State.RUNNING; | ||
| do { | ||
| state = executeCommand(gameService, boardService, state, roomId); | ||
| } while (state != State.END); | ||
| } | ||
|
|
||
| private State executeCommand(GameService gameService, BoardService boardService, State state, Long roomId) { | ||
| try { | ||
| Command command = CommandRouter.findCommendByInput(InputView.readCommend()); | ||
| return command.execute(gameService, boardService, roomId); | ||
| } catch (RuntimeException error) { | ||
| OutputView.printError(error); | ||
| return state; | ||
| } | ||
| } | ||
|
Comment on lines
+45
to
+53
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요청을 처리하기 위해 복수의 서비스 클래스가 필요하네. 요청을 수행하는 것을 하나의 트랜잭션으로 보고 해당 트랜잭션 내부에서 여러 서비스 클래스가 필요하다면 응용 서비스로직이 많이 어려워질 수 있다는 생각이야. 그런데 내가 보기에도 쉽지 않은 개선인 것 같긴 하네 🫠
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리뷰어께도 추상화가 적절히 이루어졌는지 의문이 든다는 피드백을 받았는데, 확실히 다시 고민해봐야할 부분인 것 같아. 정확하게 잘 짚어준듯👍 |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package chess.controller; | ||
|
|
||
| public enum State { | ||
|
|
||
| RUNNING, | ||
| END | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package chess.controller.command; | ||
|
|
||
| import chess.controller.State; | ||
| import chess.service.BoardService; | ||
| import chess.service.GameService; | ||
|
|
||
| public interface Command { | ||
|
|
||
| State execute(GameService gameService, BoardService boardService, Long roomId); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package chess.controller.command; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.function.Function; | ||
|
|
||
| public enum CommandRouter { | ||
| START("start", Start::new), | ||
| END("end", End::new), | ||
| MOVE("move", Move::new), | ||
| STATUS("status", Status::new); | ||
|
|
||
| private static final int COMMAND_INDEX = 0; | ||
|
|
||
| private final String value; | ||
| private final Function<List<String>, Command> command; | ||
|
|
||
| CommandRouter(String value, | ||
| Function<List<String>, Command> command) { | ||
| this.value = value; | ||
| this.command = command; | ||
| } | ||
|
|
||
| public static Command findCommendByInput(List<String> commandInput) { | ||
| if (commandInput == null || commandInput.size() == 0) { | ||
| throw new IllegalArgumentException("빈 값 입력을 허용하지 않습니다."); | ||
| } | ||
| return Arrays.stream(values()) | ||
| .filter(commandRouter -> commandRouter.value.equals(commandInput.get(COMMAND_INDEX))) | ||
| .map(commandRouter -> commandRouter.command.apply(commandInput)) | ||
| .findAny() | ||
| .orElseThrow(() -> new IllegalArgumentException("올바르지 않은 명령어 입력입니다.")); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package chess.controller.command; | ||
|
|
||
| import chess.controller.State; | ||
| import chess.service.BoardService; | ||
| import chess.service.GameService; | ||
| import java.util.List; | ||
|
|
||
| public class End implements Command { | ||
|
|
||
| private static final int END_COMMAND_SIZE = 1; | ||
|
|
||
| public End(List<String> commandInput) { | ||
| if (commandInput.size() != END_COMMAND_SIZE) { | ||
| throw new IllegalArgumentException("게임 종료 명령어 입력 형식이 올바르지 않습니다."); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public State execute(GameService gameService, BoardService boardService, Long roomId) { | ||
| return State.END; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package chess.controller.command; | ||
|
|
||
| import chess.controller.State; | ||
| import chess.domain.board.position.Column; | ||
| import chess.domain.board.position.Position; | ||
| import chess.domain.board.position.Row; | ||
| import chess.service.BoardService; | ||
| import chess.service.GameService; | ||
| import chess.service.dto.ChessGameResult; | ||
| import chess.view.OutputView; | ||
| import chess.view.mapper.ColumnMapper; | ||
| import chess.view.mapper.RowMapper; | ||
| import java.util.List; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| public class Move implements Command { | ||
|
|
||
| private static final Pattern POSITION_REGEX = Pattern.compile("" | ||
| + "move\\s+([a-h][1-8])\\s+([a-h][1-8])"); | ||
|
Comment on lines
+18
to
+19
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정규식... 고수인가? 정규식 나중에 알려주라 👊
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 조금 복잡한 정규식은 지쌤..(gpt) 도움을 많이 받긴해 😂 이걸 다 외우는건 효율적으로도 말이 안된다고 생각함 하하 |
||
|
|
||
| private final Position from; | ||
| private final Position to; | ||
|
|
||
| public Move(List<String> commandInput) { | ||
| validateMoveCommandPattern(commandInput); | ||
| String fromPosition = commandInput.get(1); | ||
| String toPosition = commandInput.get(2); | ||
| this.from = createPosition(fromPosition.substring(0, 1), fromPosition.substring(1, 2)); | ||
| this.to = createPosition(toPosition.substring(0, 1), toPosition.substring(1, 2)); | ||
| } | ||
|
|
||
| private void validateMoveCommandPattern(List<String> commandInput) { | ||
| String moveCommand = String.join(" ", commandInput); | ||
| if (!POSITION_REGEX.matcher(moveCommand).matches()) { | ||
| throw new IllegalArgumentException("게임 이동 명령어 입력 형식이 올바르지 않습니다."); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public State execute(GameService gameService, BoardService boardService, Long roomId) { | ||
| if (boardService.isCheckmate(to, roomId)) { | ||
| moveAndPrintBoard(gameService, boardService, roomId); | ||
| ChessGameResult chessGameResult = gameService.generateGameResult(roomId); | ||
| OutputView.printChessGameResult(chessGameResult); | ||
| return State.END; | ||
| } | ||
| moveAndPrintBoard(gameService, boardService, roomId); | ||
| return State.RUNNING; | ||
| } | ||
|
|
||
| private void moveAndPrintBoard(GameService gameService, BoardService boardService, Long roomId) { | ||
| boardService.movePiece(from, to, roomId); | ||
| OutputView.printBoard(boardService.getAllPieces(roomId)); | ||
| } | ||
|
|
||
| private Position createPosition(String requestColumn, String requestRow) { | ||
| Column column = ColumnMapper.findByInputValue(requestColumn); | ||
| Row row = RowMapper.findByInputValue(requestRow); | ||
| return new Position(row, column); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package chess.controller.command; | ||
|
|
||
| import chess.controller.State; | ||
| import chess.service.BoardService; | ||
| import chess.service.GameService; | ||
| import chess.view.OutputView; | ||
| import java.util.List; | ||
|
|
||
| public class Start implements Command { | ||
|
|
||
| private static final int END_COMMAND_SIZE = 1; | ||
|
|
||
| public Start(List<String> commandInput) { | ||
| if (commandInput.size() != END_COMMAND_SIZE) { | ||
| throw new IllegalArgumentException("게임 시작 명령어 입력 형식이 올바르지 않습니다."); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public State execute(GameService gameService, BoardService boardService, Long roomId) { | ||
| OutputView.printBoard(boardService.getAllPieces(roomId)); | ||
| return State.RUNNING; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package chess.controller.command; | ||
|
|
||
| import chess.controller.State; | ||
| import chess.service.BoardService; | ||
| import chess.service.GameService; | ||
| import chess.view.OutputView; | ||
| import java.util.List; | ||
|
|
||
| public class Status implements Command { | ||
|
|
||
| private static final int STATUS_COMMAND_SIZE = 1; | ||
|
|
||
| public Status(List<String> commandInput) { | ||
| if (commandInput.size() != STATUS_COMMAND_SIZE) { | ||
| throw new IllegalArgumentException("게임 점수 명령어 입력 형식이 올바르지 않습니다."); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public State execute(GameService gameService, BoardService boardService, Long roomId) { | ||
| OutputView.printTeamScore(gameService.generateGameResult(roomId)); | ||
| return State.RUNNING; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package chess.domain.board; | ||
|
|
||
| import chess.domain.board.position.Column; | ||
| import chess.domain.board.position.Position; | ||
| import chess.domain.board.position.Row; | ||
| import chess.domain.piece.Color; | ||
| import chess.domain.piece.Piece; | ||
| import chess.domain.piece.PieceType; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| public class BoardFactory { | ||
|
|
||
| public Map<Position, Piece> initialize() { | ||
| Map<Position, Piece> map = new HashMap<>(); | ||
| initializeBlackTeam(map); | ||
| initializeWhiteTeam(map); | ||
| return map; | ||
| } | ||
|
|
||
| private void initializeBlackTeam(Map<Position, Piece> map) { | ||
| initializePawn(map, Row.SEVEN, Color.BLACK); | ||
| initializeHighValuePiece(map, Row.EIGHT, Color.BLACK); | ||
| } | ||
|
|
||
| private void initializeWhiteTeam(Map<Position, Piece> map) { | ||
| initializePawn(map, Row.TWO, Color.WHITE); | ||
| initializeHighValuePiece(map, Row.ONE, Color.WHITE); | ||
| } | ||
|
|
||
| private void initializePawn(Map<Position, Piece> map, Row row, Color color) { | ||
| for (Column column : Column.values()) { | ||
| Position position = new Position(row, column); | ||
| if (color == Color.WHITE) { | ||
| map.put(position, new Piece(PieceType.WHITE_PAWN, color)); | ||
| } | ||
| if (color == Color.BLACK) { | ||
| map.put(position, new Piece(PieceType.BLACK_PAWN, color)); | ||
| } | ||
| } | ||
|
Comment on lines
+32
to
+40
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 뎁스가 깊어진다고 해도 이러한 형태로 풀어쓰는 것이 개인적으로 가독성 좋다고 생각 👍 |
||
| } | ||
|
|
||
| private void initializeHighValuePiece(Map<Position, Piece> map, Row row, Color color) { | ||
| map.put(new Position(row, Column.A), new Piece(PieceType.ROOK, color)); | ||
| map.put(new Position(row, Column.H), new Piece(PieceType.ROOK, color)); | ||
|
|
||
| map.put(new Position(row, Column.B), new Piece(PieceType.KNIGHT, color)); | ||
| map.put(new Position(row, Column.G), new Piece(PieceType.KNIGHT, color)); | ||
|
|
||
| map.put(new Position(row, Column.C), new Piece(PieceType.BISHOP, color)); | ||
| map.put(new Position(row, Column.F), new Piece(PieceType.BISHOP, color)); | ||
|
|
||
| map.put(new Position(row, Column.D), new Piece(PieceType.QUEEN, color)); | ||
| map.put(new Position(row, Column.E), new Piece(PieceType.KING, color)); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추상화가 잘 되어 있고 의존관계가 복잡해지는 만큼 의존성 주입자 Config 클래스를 운용해보는 것도 나쁘지 않을 듯!
과할수도 있다고 생각할 수도 있으려나? 근데 나는 현재 코드 볼륨에 적용하기 괜찮을 것 같아 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 나도 같은 생각을 하긴 했었는데, 리비도 그렇게 느끼는구나
아마 2단계 들어가면 이 주제로 대화해볼 기회가 있지 않을까 싶어👍