-
Notifications
You must be signed in to change notification settings - Fork 0
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
[Refactor] 프로젝트 구조 변경 및 서비스 코드 수정 #14
Conversation
- 이미 예약된 슬롯을 예약할 경우, 예외 메시지 수정
@@ -45,11 +43,11 @@ public DailyBookingStatusRes getDailyBookingStatus(Long placeId, LocalDate date) | |||
@Transactional | |||
public BookingRes book(Long loginId, Long placeId, LocalDate date, LocalTime time, | |||
Integer partySize) { | |||
validateUserExist(loginId, "존재하지 않는 사용자의 요청입니다."); | |||
validatePlaceExist(placeId, "존재하지 않는 식당입니다."); | |||
userService.validateUserExist(loginId, "존재하지 않는 사용자의 요청입니다."); |
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.
이름이 validateUserExist이니까, errorMessage도 userService가 가지고 있는 것이 더 바람직하지 않을까요? :-)
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.
loginId
를 확인하는 것이면, "존재하지 않는 사용자의 요청입니다"가 필요하고, 다른 서비스에서 사용자를 조회할 때는 "존재하지 않는 예약자입니다" 이런식으로 사용하는 입장에서 다른 에러 메시지를 전달해주고 싶을 것 같다고 생각해서 errorMessage
도 매개변수에 포함 시켰습니다!
차라리 메서드를 오버로딩 해서 필요할 때만 errorMessage를 추가하도록 하는 것이 나을까요? 아니면 에러 메시지를 구체적으로 내려주지 말고 하나로 통일하는 것이 나을까요..🤔 아니면 혹시 메서드명이 잘못된 것일까요?😅
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.
아, 이해했습니다. 이런 경우라면, vlidateUserExist를 boolean으로 하고, 그걸 받아서 에러를 내보내는 로직을 BookingService에 넣는 것이 더 좋을 것 같다는 생각이 드네요. 😎
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.
c22a745 반영했습니다:)
validateUserExist(loginId, "존재하지 않는 사용자의 요청입니다."); | ||
validatePlaceExist(placeId, "존재하지 않는 식당입니다."); | ||
userService.validateUserExist(loginId, "존재하지 않는 사용자의 요청입니다."); | ||
placeService.validatePlaceExist(placeId, "존재하지 않는 식당입니다."); |
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.
same as the above
public ApiResult<PayDepositRes> payDeposit( | ||
@RequestBody @Valid PayDepositReq request | ||
) { | ||
// TODO: 예약금 결제 비즈니스 로직 호출 |
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 static void validateUserId(Long userId) { | ||
if (isNull(userId)) { |
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.
헉 이런 메서드가..! 반영했습니다:) d6e8029
throw new IllegalArgumentException("이미 예약된 테이블입니다."); | ||
} | ||
|
||
public void book() { |
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.
서비스에서 bookingSlot.setBooked(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.
setter보다 비즈니스 의미를 더 잘 전달하고 있는 것 같습니다!
현재는 예약을 취소하는 로직이 필요하지 않은데요(물론 추후 추가가 되겠지만..) setter를 쓰면 불필요하게 많은 권한(옵션)을 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.
그런데 반대로는 어차피 book()을 부르면, 똑같은 작업을 할 수 있으니, 권한을 부여하는 측면에서는 같은거 아닐까요? :-) 오히려 비지니스가 BookingSlot에 숨는 느낌이 들어서 ...
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.
dd5906a 반영했습니다:)
멘토님 말씀듣고 고민이 되는 것이.. 전 지금까지 객체지향, DDD를 공부하면서 'setter()는 캡슐화를 위반하는 것이다.', '비즈니스 로직을 도메인 내부로 캡슐화를 하고, 서비스 레이어에는 작업의 플로우가 한 눈에 들어오도록 하는 것이 좋다'와 같이 생각을 했었는데, 저번에 멘토님과 대화 나눈대로 사실 웹 API라는 것이 객체지향을 100% 만족시키지 못하기도 하고.. 실무에서도 이론적인 부분보단 조금 더 실용적인 방향으로 개발을 하는 것 같다라는 생각이 들었습니다! 그래도 여러 채용 공고에서 객체지향 OOP를 언급하기도 하는 걸 보면.. 어떨 때는 또 객체지향을 고려해서 코드를 짜야할 것 같은데.. 언제 어떻게 적절하게 사용을 해야할지 모르겠네요😢
말씀주신 부분에서도 저는 비즈니스 로직이기 때문에 도메인(Booking, BookingSlot)에 넣은 것이었는데, 비즈니스 로직을 서비스단으로 꺼내서 처리를 하는 것이 더 적합할까요?
try (MockedStatic<BookingStatus> mockedStatic = mockStatic(BookingStatus.class)) { | ||
// given | ||
when(slot.getId()).thenReturn(bookingSlotId); | ||
mockedStatic.when(() -> BookingStatus.getStatusAfterBooking(slot)) |
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.
이 부분도 괜찮은데, slot의 데이터를 적절히 mocking해도 동일한 결과를 얻을 수 있지 않을까요?
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.
맞습니다! 그런데 테스트 코드를 보는 사람의 입장에서 테스트 대상인 Booking
뿐만 아니라 BookingStatus
구현 내용도 이해해야되서 바로 getStatusAfterBooking()
메서드를 모킹하긴 했습니다! 그런데 static 메서드를 모킹하는 것이 코드가 복잡하긴 하더라구요.. slot 데이터를 모킹하는 것이 더 나을까요?
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.
네, 그런 의도라면, static mocking이 괜찮은 것 같습니다. 👍
slot.book(), | ||
partySize | ||
BookingStatus.getStatusAfterBooking(slot), | ||
isNull(partySize) ? 1 : partySize |
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.
이건 validatePartySize에서 검증이 끝난거 아닐까요?
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.
partySize는 Nullable한 필드여서 Null이면 기본값인 1을 저장합니다!
validatePartySize()
에서는 Null이 아닐 때만, 인원 수가 1 이상인지 확인하는 메서드입니다!
사실 컨트롤러 단에서 Null이면 1을 넣어주긴 하는데.. 혹시나(?)하는 마음에 도메인에도 해당 로직을 넣었습니다!
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.
리뷰가 늦었습니다. 🙏 수고하셨습니다. 👍
boolean exist = placeService.existsById(placeId); | ||
|
||
// then | ||
assertThat(exist).isTrue(); |
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.
assertThat(exist).isTrue(); | |
assertTrue(exist); |
🔗 관련 이슈
Resolves #13
👩🏻💻 구현 내용
💬 코멘트
feat/#8-develop-booking
으로 설정했는데, base를 main으로 하고 [Feat] 예약 현황 조회 / 예약 하기 기능 구현 #12 를 볼 필요없이 이 PR만 보면 되도록 하는게 나을까요??