콘텐츠로 이동

2021 06 13

2021-06-13

나의 PR을 소개합니다 Chess

  • 포모 - RequestBody로 넘어온 Dto에 래퍼타입 vs 기본형
    class Request {
        Integer age;
    }
    
      - 이렇게 래퍼 클래스를 쓴다면 NPE에 대한 사항을 고려해줄 것
      - 기본형은 default로 0이 할당되기에 그에 대한 처리를 고려해줄 것
      - 래퍼타입으로 사용하고 Bean Validation으로 `@NotNull`붙여주는 것이 좋아보임
    

    - 예상치 못한 Exception을 위한 @ExceptionHandler 필요한가? - 새롭게 정의한 Exception이 여기로 흘러들어갈 수 있음 - 너무 범용적으로 에러를 다 잡아서 오히려 개발자 입장에서 디버깅하기 어려울 수도

  • 우기 - API 설계시 /api/v1/뭐시꺵이 추천 - Repository vs Dao - Repository를 Domain의 일급 컬렉션(List)으로 생각해보는 것을 추천 - Dao는 테이블에 1:1 대응 - Dao에서 예외를 안 뱉고 처리를 온전히 하는 경우에 대한 예외 상황 고려도 해볼 것 - ex. 없는 것 삭제 등 - RequestDto를 어느 레이어까지 사용해야 할까? - 서비스까지 내리라는 게이츠의 피드백 - 우기는 Controller에서 도메인을 만들어 서비스에게 주는 것을 선호
  • 완태 - Service에서 RequestDto를 처리하자 - 서비스에서 Dto를 통해 데이터를 주고 받으며 도메인을 보호할 것! - ResponseBody 와 ResponseEntity 중에 무엇을 사용할까? - RestController에 ResponseBody 어노테이션 포함
  • 느낀점 - 내가 지금 서비스를 작성한 것을 보니까 우후 죽순이네 1. Controller에서 Dto 해체하고 Service에 "필요한 필드를 추출하여" 파라미터로 넘겨줌 2. Service에서 Service를 호출할 때에는 또 파라미터로 "Domain" 자체를 넘겨줌 3. 마지막 Fare 스켈레톤에서는 Controller에서 Service한테 "Dto"를 그냥 고대로 넘겨줌 - Controller가 도메인을 만드느냐 VS Service가 RequestDto를 아느냐 정도의 차이로 보임 - 유지보수가 조금 힘들더라도 Service단에서 부터 Domain을 사용하는게 맞아보임 - Controller에서 Domain을 만들어내린다 == Controller가 도메인을 안다 - Presentation Layer가 Domain을 모르게 하기 위해 Dto를 사용하는 것인데 말이지 - Dto를 나는 Presentation Layer <-> Service Layer의 중재자로 보기로 했음 - 그렇다면 Service까지는 Dto가 와도 된다 생각 - 그래도 Service에서 Controller로 응답을 보낼떄엔 ResponseDto로 감싸서 보내주는 것이 좋아보임 - Domain을 Service Layer까지 사용하는 것으로 보호한다 볼 수 있을 듯 - Service에서 Service로 응답을 보낼 때에는 Domain 그 자체를 보내주는것이 불가피 할 듯 - 어쨋든 같은 Layer 간의 소통이기 때문에 도메인을 사용해도 괜찮아보임! - [나만의 줏대] - Controller <-> Service 간의 메서드 매개변수/응답은 DTO로 사용하자! - Service <-> Service 간의 메서드 매개변수/응답은 Domain으로 사용하자! - Enum으로 예외를 관리한다는게 무슨소리지? - 참고: https://velog.io/@waldo/%EC%97%90%EB%9F%AC%EC%B2%98%EB%A6%AC101-Enum%EC%9C%BC%EB%A1%9C-%EC%97%90%EB%9F%AC%EC%BD%94%EB%93%9C-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0 - ErrorCode Enum 클래스를 만들어 예외에 대한 정보를 적어둠 - ErrorResponse 클래스를 만들어 생성자 매개변수로 ErrorCode를 갖고 있도록 함 - 잠깐만... 패키지 내부에 Exception 클래스 만들어서 에러메시지 저장해두고 했자나 - 그래서 @ExceptionHandler로 야무지게 예외 잡고, Exception 클래스 내부에서 메세지 꺼내서 ErrorResponse만들어줬자나 - 음... Enum으로 관리하게 되면 Exception에 대한 정보를 Enum으로 한번 더 추가적으로 정의해줘야 하는 것 같은데? - 한눈에 Enum으로 프로젝트에서 발생할 수 있는 예외를 볼 수 있다는 응집도 면에선 좋아보여 - 그런데 Exception 클래스를 네이밍 잘 지어줘서 예외처리해줘도 괜찮을 것 같은데?

나의 PR을 소개합니다 Subway-Map

  • 포모 - 테스트만을 위한 프로덕션 코드 지양할 것 - 테스트 클래스 내부에서 "테스트 픽스쳐"를 만들어서 사용하자 - ex. 지하철역_등록되어_있음(강남역); <-- 이런거! - @Transactional 을 클래스 처리 단위로 사용할 때엔 readOnly = true 속성을 넣어두자 - Dao 처리를 할 때 Domain을 매개변수로 넘겨주자 - lineDao.save(Line line) >> lineDao.save(Long id, String name...)
  • 우기 - DB에 의존적이지 않은 테스트를 구현 - @Sql("classpath:~~.sql")을 통해 테스트 수행 전 쿼리문을 실행해보자 - JdbcTemplate의 DataAccessException을 Service에서 의미있게 포장하여 예외 처리 - @Transactional이 동시성 처리를 어떻게 보장하는가? - 애초에 DB에 동시성이 어떻게 보장되는 지를 조금 살펴봐야 할 듯
  • 완태 - @MockBean vs @Mock - @MockBean: @SpringBootTest를 하면 Bean을 MockBean으로 덮어씌움 - @Mock: 이걸로 테스트 자체를 실행할 수 있음. 따라서 빨라짐 - Mockito를 통해 테스트를 작성한다 == 내부구현을 다 알고 있다 - 테스트와 프로덕션 코드의 긴밀한 결합 - 유지보수 포인트 2배 - 참고: https://github.com/woowacourse/jwp-refactoring/pull/2 - Mockito를 엄격하게 사용하자! - Interface를 통해서 내부 구현이 바뀌어도 Interface에서 선언한 메서드만 잘 동작하면 되는 거자나? - 유연한 코드 작성 가능 - 내부적으로 어떻게 동작하는지 알고 짠 Mock 테스트는, 리팩토링/구현변경으로 부터 자유롭지 못함 - 그럼 어떻게 Mockito를 써야할까? 1. 제어할 수 없는 영역 - Random/Shuffle/LocalData.now()/HTTP/외부 저장소 등 2. Local 구성이 가능하다면 쓰지 말 것! - 저장소를 Mock한다 == 신뢰할 수 없는 테스트 - 저장소 테스트하라고 h2 제공해주는 것 3. Layering의 경계에서 사용 - 각 계층을 테스트할 때 하위 계층을 위한 코드를 방대하게 작성하는 것보단 Mockito가 좋을 수 있음
  • 느낀점 - 아? 내가 테스트를 위한 테스트를 작성중이였구나 - Mock을 쓴다는 것 자체가 어쩌면 내가 TDD를 안했기 때문일 수도 있겠다 - TDD를 한다는 것 자체가 정말 리팩토링을 자유롭게 할 수 있도록 프로덕션을 짜게 하는 힘이 있겠구나 - 테스트 코드를 작성할 때, 조금 더 신경쓰자 - 리팩토링을 자유롭게 하고 Test Run 하면 촤르르 통과해야 테스트로서의 가치가 있지 않겠어? - 초록불을 위한 테스트 말고, 정말 검증 가치가 있는 테스트를 쓰자 - @Transactional을 너무 무책임하게 띡띡 쓰고 있구나 - 토비 5장 읽자!