페어와 같이 고민하고 진행하는 방식은 좋았다. 그러나 우리 모두 설계에 너무 많은 시간을 투자했다. 그러다 보니 마감 기한 내에 제대로 완성하지 못하고 제출했다. 무엇보다 기한 내에 쓰레기 코드라도 완성해서 제출해야 했는데 하지 못한 게 아쉬웠다.

도메인에서 다른 Piece들은 괜찮았는데 Pawn이 문제였다. 갈 수 있는 곳과 상대편 말을 잡을 수 있을 곳이 달라서 꽤나 고생했다.

박재성의 DAO 리펙토링을 보며 DAO에 대해서 조금씩 리펙토링을 해봤다. 점진적으로 개선되는 내 코드를 보니 기분이 좋았다.

나중에 여러 명이 접속할 때를 대비해서 서비스 레이어와 DAO 레이어를 상태값을 가지지 않도록 했다.

많은 고민을 하게 했던 3가지는 아래와 같다.

  1. Pawn의 전략패턴 사용
  2. 멀티스레드에 대한 고민(상태값에 대한 고민)
  3. 싱글톤에 대한 고민

마감 기한을 꼭 지키자. 완성하고 리펙토링하자 :)

내가 받았던 피드백

  • File은 자바 코어에 존재하는 클래스명이라 피하는 것이 좋다
    • 체스에서 rowcolumnrankfile로 얘기하더라. 처음 알았다;;
  • 보기 쉬운 코드도 좋지만 최대한 서로 의존하지 않는 코드를 만들자
    • Command를 인자로 넘길까, Position을 인자로 넘길까에 대한 내용이었다.
  • 입력 레이어와 비즈니스 레이어에 대한 경계를 나누자. 그래야 웹에 적용할 때도 변경이 적다.
  • 빈 칸에 대한 처리는 Null이 나올 수 있으므로 Piece를 상속한 Blank 라는 클래스로 작성해본다.
    • 이게 Null 객체 패턴인데 그 클래스 안에서 아무 것도 안하면 된다.

다른 크루들의 피드백

  • DAO를 테스트하기 위해서 Mock 객체를 사용한다
  • 게임의 상태에는 여러 상태가 있을 수 있으니boolean 값으로만 정해놓지말자.(가령 PLAYING, ENDED 등등… 여러 상태가 추가될 수 있다)
  • 인터페이스를 구현한 클래스 명에 Impl이라는 단어 사용을 지양하자
  • 인터페이스를 둘 만큼 공통 부분을 분리해야 하는 이슈가 없다면 분리하지 말자.
  • Optional의 경우 필드에서 사용하는 것을 지양해야 한다. Optional은 변수의 Null 유무를 파악하기 위해 나왔다. 메서드의 반환에서만 사용하도록 해야한다.
  • 멀티 스레드의 동기화 이슈때문에 대부분의 자바 기반의 웹 개발 시 의존하고 있는 객체는 몇몇 예외 케이스를 제외하고 상태가 없는 클래스를 의존하도록 구현한다.
  • isPawn, isKing과 같이 현재 객체를 확인하는 메서드는 확장에 상당히 안 좋은 메서드다. 왜냐하면 매번 메서드를 추가해야하니까. 가능하면 이런 메서드는 사용하지 않고 구현해보자
  • DAO, DTO에 대한 클래스도 UpperCamelCase로 작성한다.

배운 내용

이미지 경로를 Mapping 해줄 때 서버와 클라이언트 중 어느 곳에서 해주는 것이 더 나은가?

  • 시스템 성격에 따라 다르다
  • 조심해야될 점은 ajax 통신을 할 때, 새로고침되지 않은 상태에서 새로운 Piece가 등장했을 때 이미지 경로를 클라이언트에서 처리한다면 호환되는 이미지를 찾을 수가 없게 된다. 이처럼 데이터의 성격이 클라이언트 코드에 의존적이지 않게 할 때는 반드시 서버에서 데이터를 처리해줘야 한다.
  • 반대 케이스는 한 번 배포되면 변경할 수 없는 클라이언트(앱과 같이 신규 버전과 하위 버전 등등…)가 있을 때, 응답이 신규 버전과 하위버전이 나뉘기 때문에 서버에서 데이터를 컨트롤할 필요는 없어지게 된다.

싱글턴을 사용하는 기준

  • 객체에 대한 생성 비용이 크고, 고정적일 때 싱글턴을 사용한다
  • 예를 들어, 커넥션은 비용이 큰데 커넥션을 매번 생성하지 않고 재활용 하기 위해 싱글턴을 사용할 수 있다.

공유되는 자원이 존재한다면 항상 멀티스레드에 대한 접근을 고려해야한다.

스프링 프레임워크의 싱글 오브젝트(Bean)

  • 싱글 오브젝트는 AOPIoC를 위해 Context에 유일한 싱글 오브젝트를 만들고 생성, 소멸에 관여할 수 있도록 설계됐다.
  • 싱글턴과 유사한 성격으로 비용을 줄이는 용도로도 싱글 오브젝트를 사용할 수 있다. 다만 싱글턴과는 접근의 목적과 사용이 다르다.
  • bean을 싱글턴이라고 부르는 경우가 있는데 잘못된 표기이고, 싱글오브젝트가 더 맞는 표현이다.

그 이외

  • ajax는 비동기 방식이며 form은 동기 방식이다
  • Service와 DAO에 싱글턴을 적용한 이유
    • 필드가 없다면 유틸리티 클래스와 같이 메서드를 전부 static으로 변환해줄지 고민해야한다.
    • 그러나 ServiceDAO를 전부 static으로 바꿀 수 없는 이유는 인터페이스를 둬서 유연성을 주기 위함이다. DAO같은 경우는 Oracle, Mysql과 같이 여러 곳에서 바꿀 수 있도록 유연성을 주고 Service도 다른 서비스로부터 유연성을 가지기 위해 고민해야 한다.
  • source에 빈 칸을 선택했을 때 어차피 Blank라 갈 곳이 없다. 예외처리를 해주지 않아도 된다
  • Junit5에는 적폐코드가 있다. isIn, GreaterThan, LessThan between등등… 크고 작고는 테스트코드 안에서 충분히 작성할 수 있으므로 사용하지 말자
  • 초기화를 할 때도 전략 패턴을 사용하 할 수 있다. initialStrategy, emptyStrategy, defaultStrategy, 등등…
  • 모든 것을 immutable하게 만들자
  • Collections.Unmodified 써도 바뀐다. 그래서 불변하도록 만드려면 new ArrayList<>(요기)에 넣는 게 좋다.