Skip to content

Conversation

@fucct
Copy link

@fucct fucct commented Apr 6, 2020

안녕하세요! 리뷰어님 DM으로 질문을 드렸는데 바쁘셔서 못보신 것 같아요!
미션 종료가 얼마 남지 않아서 일단 그동한 했던 2~3주차 미션도 함께 제출합니다! 함께 리뷰해주시면 감사하겠습니다.
혹시라도 DM을 못보셨을까봐 여기에 다시 질문 남기겠습니다!

안녕하세요 리뷰어님! 피드백 잘 받았습니다! 다름이 아니라 status와 나머지 구현에 대해 질문이 있는데요! 점수가 Running State에서도 계산되도록 하여서 실시간으로 사용자에게 자신과 상대방의 점수를 보여주려고 구현을 했었습니다. 마찬가지로 End State에서도 Board를 보고 결과를 알 수 있도록 하려고 구현을 했었습니다. 코치님들께도 구현부분에 있어선 자유롭게 해도 된다고 하셔서 이렇게 했고, 강의자료에도 정확하게 구현에 대한 예시가 없어서 헷갈려서 질문 드립니다. RunningState에서는 점수 계산 없이 보드만을 보여주고, End State에서는 Board를 보여주지 않고 점수만을 보여주어야 하는 건가요? 답변주시면 감사하겠습니다 😄

그리고 추가적인 질문도 드리겠습니다!
State 패턴을 사용했던 것이 도메인 상에선 관리가 좋고 배운것을 활용하기 위함이였는데요, 웹상에서 State 패턴이 오히려 구조를 복잡하게 하고 에러를 많이 발생시켜서 제거하고 End인지를 확인하는 메소드만 추가를 했는데 사실 어떤 설계가 더 좋은지 확실치 않네요! 조언주시면 반영하도록 하겠습니다.
두번째 질문은 web Controller가 Console Controller와 맞지 않아서 분리를 하였는데 이게 좋은 방법인지 잘 모르겠습니다. 실제로 컨트롤러를 여러개를 두고 사용을 하기도 하나요?
세번째 질문은 명령어에 따라 세부적으로 받아야 하는 response의 내용도 다양하게 달라지는데, 그런 경우에 Dto 클래스를 분리하는 방식으로 설계를 하는게 좋을까요? 아니면 모든 데이터를 가질 수 있는 Dto를 만들어서 사용하지 않는 부분을 null로 초기화 해주는 방식이 좋을까요?

답변주시면 감사하겠습니다!😅

fucct added 28 commits March 24, 2020 15:07
	- Position은 내부적으로 file과 rank를 알고 있다.
	- Position을 map으로 캐싱해서 String 입력 값에 따라 해당하는 position 객체를 반환
	- Piece는 자신의 위치를 안다
	- Piece는 자신이 속한 Player를 안다
	- Board를 초기화하기 위한 BoardInitializer 인터페이스 추가
	- Board initializer가 사용할 초기 데이터인 InitialPieceRepository 추가
	- EnumRepositoryBoardInitializer에서 repository를 참고하여 board 초기화
	Todo.
	- 장애물이 있을 경우 판단하는 로직 구현 필요
	- Knight를 제외한 다른 piece의 이동 규칙 구현 필요
	- 게임의 진행 상태를 나타내는 State 생성
	- Application 로직에 있던 내용을 Controller로 이동
	- InputView의 리팩토링
	- Board 출력을 위한 ResponseDto 생성
	- OutputView에서 ResponseDto로 출력하는 로직 구현
	- Piece의 색에 따라 toString 구현
	- 한 게임을 관리하는 ChessGame 생성
	- 이동을 위한 파라미터 객체인 MoveParameter 생성
	- EnumRepository에서 생성된 피스를 가지지 않고, 피스 generator를 가지고 있도록 변경
	- EnumRespositoryInitializer에서는 해당하는 generator로 피스를 생성하여 보드 초기화
- 이동 규칙에 적합하게 움직이는 지 테스트
- 중복되는 메서드를 템플릿 메서드로 분리
- PieceState를 적절하게 반환하도록 구현
- Piece의 상태에 따라 Ready, Running, End로 분리
- Rook Test 구현
- Direction 개념 구현
- Direction 에 맞게 position 이동 구현
- Rook 이동 구현
- Bishop Test 구현
- Direction 이 음수도 나오도록 수정
- Direction 에 맞게 position 이동 수정
- Bishop 이동 구현
- King Test 구현
- Direction 에 존재하지 않는 target의 경우 예외처리
- King 이동 구현
 - 현재 Trun인 플레이어만 move가 가능하도록 구현
 - 각 Piece 이동에 맞게 테스트 refactor
 - Pawn 이동 규칙에 맞게 분리
 - 플레이어 체크 안되는 버그 수정
- 접근제어자 추가
- 불필요한 객체 삭제
- 매직넘버 상수화
- 가독성이 떨어지는 메서드 분리
- indent 줄이기 위해 메서드 분리
- status 결과 객체 구현
- 결과 계산시 종료 구현
              - 컨벤션 리팩토링
              - 테스트 에러 수정
- state 패턴 삭제
- service layer 추가
- indent 규칙에 맞게 리팩토링
- 기타 컨벤션에 맞게 수정
- Index page에 접근가능하도록 구현
- Index page에서 현재 존재하는 방 목록 보여주도록 구현
- DB에 접근하여 방 목록을 가져오도록 구현
- 저장시 DB에 저장
- 불러오기 시 DB 로부터 게임 load
- 진행중인 게임을 저장하지 않고 종료시 DB 삭제
- 진행중인 게임에서 새 게임 플레이 가능
@fucct fucct force-pushed the pair-db branch 2 times, most recently from 089314f to 2f4375b Compare April 8, 2020 11:51
Copy link

@jeonghoon1107 jeonghoon1107 left a comment

Choose a reason for hiding this comment

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

안녕하세요 디디!
몇가지 피드백을 남겼으니 확인부탁드려요 :)

  1. 제가 이야기 한 것은 State에서 점수를 계산하는 것을 이야기 한 것이에요!
  2. 상태 관리 -> 주로 이벤트 기반으로 상태를 관리하는데 현재 구조에서는 한계가 있는 것 같아 보여요. 이 부분에 대해서 더 궁금하시면 DM 주세요!
  3. 현재는 controller를 분리해도 괜찮은 것 같아요. 조금 더 나아가고 싶다면 레이어를 하나 더 두는 것이 좋은 방법 같아요. adapter라던가..
  4. null로 초기화하는 것은 피하는 것이 좋을 것 같아요.

import java.util.*;
import java.util.stream.Collectors;

public class JDBCChessDAO implements ChessDAO {

Choose a reason for hiding this comment

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

카멜케이스를 지켜주세요 :)

Long id = getCurrentGameId(con);
addBoard(id, chessGame);
return id;
} catch (SQLException e) {

Choose a reason for hiding this comment

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

전체적으로 exception을 잡아서 바로 다시 던지는 행위는 불필요해보이네요.

import java.util.List;
import java.util.Map;

public interface ChessDAO {

Choose a reason for hiding this comment

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

카멜케이스!

return new ResponseDto(chessGame.getBoardAndString(), chessGame.getTurn(),
chessGame.getStatus(), id);
} catch (SQLException | IllegalArgumentException | UnsupportedOperationException e) {
return new ResponseDto(e.getMessage());

Choose a reason for hiding this comment

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

메시지를 던져주는 것 너무 좋네요 👍

public class JDBCChessDAO implements ChessDAO {
public Connection getConnection() {
Connection con = null;
String server = "localhost:13306"; // MySQL 서버 주소

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.

안녕하세요 리뷰어님! 혹시 Connection도 상수로 사용해도 문제가 없나요? 혹시 문제가 될까봐 상수로 사용하지 않았는데 상수로 바꾸는 것이 좋을까요?

try (Connection connection = getConnection()) {
Map<Position, PieceState> board = getCurrentBoard(id, connection);
Turn turn = getCurrentTurn(id, connection);
if (turn == null) return null;

Choose a reason for hiding this comment

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

}
//
//
// get("/", (req, res) -> {

Choose a reason for hiding this comment

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

불필요한 코드들인가요?

return commands.get(requestDto.getCommand()).apply(requestDto);
}

public ResponseDto start(RequestDto requestDto) {

Choose a reason for hiding this comment

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

requestDto 사용하는 변수인가요?

long id = requestDto.getId();
ChessGame chessGame = chessGames.get(id);
List<String> parameter = requestDto.getParameter();
ResponseDto responseDto = new ResponseDto("");

Choose a reason for hiding this comment

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

해당 위치에서 객체를 만들어 주고 set을 할 필요는 없을 것 같아요!

}


private ResponseDto unknown(RequestDto requestDto) {

Choose a reason for hiding this comment

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

ResponseDto안에 선언해놓고 사용할 수 있지 않을까요?


@BeforeEach
void setUp() throws SQLException {
chessService.start(null);

Choose a reason for hiding this comment

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

테스트끼리 영향을 받을 수 있기 때문에 저장소에 있는 데이터는 각 테스트 케이스마다 deleteAll을 실행하는 것이 좋을 것 같아요.

@fucct fucct closed this Apr 12, 2020
@fucct fucct reopened this Apr 12, 2020
@fucct
Copy link
Author

fucct commented Apr 12, 2020

답변 감사합니다! 제가 이번에 request 와 response 를 처음 사용해보려고 했는데 원하는 대로 깔끔하게 구현하지 못했네요 ㅠㅠ requestDto에 요청 값을 저장할 때, 사용자가 입력한 그대로인 String 을 저장해야 하는지, 아니면 사용자의 입력을 적절히 변환시켜서 저장해야 하는지 잘 모르겠습니다.. 그리고 말씀하신 것 처럼 response에 null로 초기화 되는 필드들이 많은데 이 필드들을 분리해서 여러개의 dto로 관리해야 하나요? 아니면 다른 방식으로 해야할까요? 조언해주시면 감사하겠습니다!😅

Copy link

@jeonghoon1107 jeonghoon1107 left a comment

Choose a reason for hiding this comment

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

안녕하세요 디디!
미션 진행하느라 고생하셨습니다 :)
추가적으로 궁금한 부분은 언제든 DM 주세요!


public ChessService(ChessDao chessDAO) {
this.chessDAO = chessDAO;
commands.put(Command.START, null);

Choose a reason for hiding this comment

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

빼거나 기본 request를 넣어주면 어떨까요?

import java.util.Objects;

public class ResponseDto {
private static final ResponseDto unknownResponse = new ResponseDto("알 수 없는 명령어 입니다.");

Choose a reason for hiding this comment

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

접근제어자를 public으로 변경하고 사용해도 좋을 것 같아요!

@jeonghoon1107 jeonghoon1107 merged commit 250cb50 into woowacourse:fucct Apr 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants