-
Notifications
You must be signed in to change notification settings - Fork 162
[1, 2, 3 단계 - 방탈출 예약 관리] 미아(이종미) 미션 제출합니다. #4
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
Conversation
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
Co-authored-by: jongmee <ra123221@gmail.com>
her0807
left a comment
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시부터 10시 까지 내리 했던데
열정이 대단합니다.
미아는 스프링에 대해서 구현 경험이 있다고 하셨는데요!
그래서 적절한 annotation 을 사용해서 spring 으로 view 를 적절히 반환하도록 요구사항이 충족된 것 같아요. 아주 잘하셨습니다.
그런데 레벨 1 때 저희가 연습했던 도메인 객체에 대해서 직접 요구사항을 도출해보고 검증하고, 단위테스트를 해보았던 것들이 코드에서 잘 보이지 않더라고요 ㅠㅠ
물론 요구사항에 적혀있지 않아서 그럴수도 있지만, 저희는 점진적으로 더 나음을 도모해야하니까요! 레벨 1 때 것들도 함께 챙겨나가볼까요?
| import java.util.concurrent.atomic.AtomicLong; | ||
|
|
||
| @Controller | ||
| public class AdminController { |
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.
Controller 에서 repository 를 바로 의존하고 있는데요,
그러다보니 도메인에서 DTO 를 만드는 형태로 간결함에 초점을 두고 개발해주신 것 같아요!!
가독성 좋고 읽기 깔끔하지만, 도메인에 뷰의 변경에 따른 전파가 가기 때문에
service layer 를 두어 검증과 계층 별 의존성 분리 역할을 주면 어떨까요? 😁
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.
기능 요구 사항을 만족하는 간결한 프로그램을 생각하며 구현하다 보니 전체적으로 도메인이 뷰의 변경에 영향을 받는 구조가 되었네요 🥲
Service layer를 추가하여 계층 분리를 하고, 검증(예약 id 검증)을 service layer에서 하도록 변경하였습니다. 우선 Presentation 계층인 controller만 dto를 사용하도록 하여 service에서는 dto를 생성하거나, dto에서 entity를 변환하는 로직 등은 존재하지 않도록 구현하였는데, 수달은 이에 대해 어떻게 생각하시나요?
저는 DTO의 역할이 아래와 같다고 생각합니다. (DTO를 controller에서만 사용한 이유)
- 뷰의 변경에 도메인이 영향을 받지 않고, 도메인 자체를 뷰에 노출시키지 않는다.
- 현재 DTO(ReservationResponse, ReservationSaveRequest)는 요청과 응답에서 데이터를 전달하고, 컨트롤러의 역할에서 필요하다.
이것저것 레퍼런스를 찾아보니 의견이 나뉘는 것 같은데(controller에서만 사용한다, controller와 service에서 모두 사용한다) 수달은 현재 현업에서 어떤 의견을 가지고 사용하고 계신지 궁금합니다!
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.
좋은 고민이네요!
저는 dto는 controller에서 dto -> domain 으로 변환하여 의존성을 끊어서 사용하고 있어요.
이유는 미아가 말씀해주신 영역도 있고, service layer 가 여러 곳에서 재사용될 여지가 큰데, dto 의 형태가 일정하지 않으니
재사용성에도 좋지 않고, 뷰 변경에 대한 영향도 전파되기 때문이에요!
그러나 재사용성이 적고, 뷰와 도메인이 항상 핏하게 떨어질 경우 혹은 개발 초기 단계에 빠르게 치고 나가야하는 경우에서는
controller와 service 모두 혼용해서 사용하기도 하는 것 같아요.
transfer 한다는 것은 여러 고민들이 수반되어야하기 때문인데요. (어느곳에서 어떤 형태로 변환해줄것인지 등등 또 얼마나 잘게 나눌 것인가에 대한 고민도요!)
다만,service 에서 controller 로 응답값을 반환할 때는 domain -> reseponse dto 로 꼭 변환해주는 편이에요.
controller 는 model 과 view 사이에 중개자 역할을 하는 것인데 도메인을 반환하게되면
controller 영역에서 의도치 않게 도메인에 상태를 변경할 수도 있기 때문인데요! JPA 를 써보셨다고 하셔서 첨언드리면
JPA 의 장점 중 하나인 Dirty Checking 이 일어나서 의도치 않게 변경점이 DB 까지 이어지기도 하고요!
|
안녕하세요 수달! 리뷰에 코멘트 및 질문 남겨놓았습니다 :)
|
her0807
left a comment
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.
안녕하세요 미아! ㅎㅎ
워밍업 제대로 된 것 같은데요? 🎉
질문주신 내용과 간단한 코멘트들 남겼습니다 :)
해당 코멘트들은 다음 단계 진행하면서 함께 반영해주시면 좋을 것 같아요👍🏻
|
|
||
| import java.util.List; | ||
|
|
||
| @RestController |
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.
👍🏻
|
|
||
| @PostMapping | ||
| public ResponseEntity<ReservationResponse> createReservation(@RequestBody ReservationSaveRequest request) { | ||
| var reservation = request.toReservation(); |
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.
dto, -> domain 변환할 때 toModel 이라는 메서드명을 자주 사용하는 것 같아요 🙂
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/reservations") |
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.
공통된 url 를 묶어두셨군요 👍🏻 잘하셨습니다
| if (existingSameUser) { | ||
| throw new IllegalArgumentException("동일한 시간에 같은 사용자가 예약할 수 없습니다."); | ||
| } | ||
| if (reservationsInSameDateTime.size() >= MAX_RESERVATION_PER_TIME) { | ||
| throw new IllegalArgumentException("해당 시간대에 예약이 모두 찼습니다. (최대 4팀)"); | ||
| } |
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.
검증 로직을 따로 추출해볼까요?
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.
private 메소드로 추출하였습니다 :)
| return reservationRepository.save(reservation); | ||
| } | ||
|
|
||
| public void deleteReservation(Long id) { |
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.
👍🏻
| server.servlet.encoding.charset=UTF-8 | ||
| server.servlet.encoding.enabled=true | ||
| server.servlet.encoding.force=true |
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.
오 해당 속성들은 어떤 이유로 추가하셨나요?
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.
| @DisplayName("이미 초기화된 예약 ID를 초기화(수정)할 경우 예외가 발생한다.") | ||
| void initializeId() { | ||
| // given | ||
| Reservation reservation = new Reservation(USER_MIA, MIA_RESERVATION_DATE, MIA_RESERVATION_TIME); |
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.
테스트를 위해 반복 생성되는 객체들은 Test Fixture 로 추출해도 좋을 것 같아요!
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.
그렇네요! Reservation 객체도 TestFixture로 추출하였습니다.
| } | ||
|
|
||
| @Test | ||
| @DisplayName("동일한 시간대에 최대 4팀이 예약할 수 있다. 초과되면 예외가 발생한다.") |
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.
귀여운 요구사항을 적용시켰군요 고마워요 🤩

안녕하세요 수달! Level 2 첫 미션 잘 부탁드립니다 🙇🏻♀️
웹 개발 경험