-
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] #185 - schedule, staff, cast의 add, delete, update DTO를 하나의 DTO로 변경 및 scheduleNumber를 서버측에서 부여하도록 변경 #187
Conversation
…ateService 클래스 삭제
…프를 수정하려고 할 때 에러처리 추가
private Member validateMember(Long memberId) { | ||
log.debug("Validating memberId: {}", memberId); | ||
return memberRepository.findById(memberId) | ||
.orElseThrow(() -> { | ||
log.error("Member not found: memberId: {}", memberId); | ||
return new NotFoundException(MemberErrorCode.MEMBER_NOT_FOUND); | ||
}); | ||
} | ||
|
||
private Performance findPerformance(Long performanceId) { | ||
log.debug("Finding performance with performanceId: {}", performanceId); | ||
return performanceRepository.findById(performanceId) | ||
.orElseThrow(() -> { | ||
log.error("Performance not found: performanceId: {}", performanceId); | ||
return new NotFoundException(PerformanceErrorCode.PERFORMANCE_NOT_FOUND); | ||
}); | ||
} | ||
|
||
private void validateOwnership(Long userId, Performance performance) { | ||
if (!performance.getUsers().getId().equals(userId)) { | ||
log.error("User ID {} does not own performance ID {}", userId, performance.getId()); | ||
throw new ForbiddenException(PerformanceErrorCode.NOT_PERFORMANCE_OWNER); | ||
} | ||
} |
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.
기존 다른 코드에서는 멤버 및 공연 관련 권한 확인을 아래처럼 따로 메소드로 분리하지 않고 필요한 메소드 내에서 작성하셨었는데 이렇게 분리할 경우의 이점이 뭔가요?
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new NotFoundException(MemberErrorCode.MEMBER_NOT_FOUND));
Long userId = member.getUser().getId();
Performance performance = performanceRepository.findById(ticketDeleteRequest.performanceId())
.orElseThrow(() -> new NotFoundException(BookingErrorCode.NO_PERFORMANCE_FOUND));
if (!performance.getUsers().getId().equals(userId)) {
throw new ForbiddenException(PerformanceErrorCode.NOT_PERFORMANCE_OWNER);
}
그런데 이렇게 분리하게 되면 한 서비스 내에서 검증이 반복되는 경우의 코드를 줄일 수 있을 것 같네요! 검증 과정이 반복되는 다른 서비스에 적용하면 좋을 것 같습니다!
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가 재사용성이 부족해서 기능 구현 후 2차 스프린트 때, 전반적으로 코드 리팩토링을 하고 싶은데 어떻게 생각하시나요? (DTO 부분에 대해서도 네이밍 부분을 조금 손을 봐야할 것 같습니다)
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.
저도 전반적인 코드 리팩토링 필요하다고 생각합니다! 같이 잘 논의해봐요~
// 스케줄 요청에 따라 추가 또는 업데이트된 스케줄 객체를 생성합니다. | ||
List<Schedule> schedules = scheduleRequests.stream() | ||
.map(request -> { | ||
if (request.scheduleId() == null) { | ||
return addSchedule(request, performance); | ||
} else { | ||
existingScheduleIds.remove(request.scheduleId()); | ||
return updateSchedule(request, performance); | ||
} | ||
}) | ||
.collect(Collectors.toList()); | ||
|
||
// 요청에 포함되지 않은 기존 스케줄은 삭제합니다. | ||
deleteRemainingSchedules(existingScheduleIds); |
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.
현재 한 공연당 스케쥴을 최대 3개 등록할 수 있어 addSchedule 메소드에서 스케쥴을 추가하기 전에 추가했을 때 3개가 초과하지 않는지 확인하는 로직을 하단에 작성하셨는데, 만약 기존 스케쥴 수가 3개였고 하나를 삭제, 하나를 추가할 경우 추가로직이 먼저 실행되어 정상적으로 반영되지 못할 것 같습니다.
추가 전에 삭제를 먼저 하는 것이 안전할 것 같은데, 아래와 같은 방식은 어떤가요?
// 요청에 포함된 스케줄 ID를 사용하여 기존 스케줄 목록에서 삭제할 스케줄을 제외합니다.
scheduleRequests.forEach(request -> {
if (request.scheduleId() != null) {
existingScheduleIds.remove(request.scheduleId());
}
});
// 요청에 포함되지 않은 기존 스케줄은 삭제합니다.
deleteRemainingSchedules(existingScheduleIds);
// 스케줄 요청에 따라 추가 또는 업데이트된 스케줄 객체를 생성합니다.
List<Schedule> schedules = scheduleRequests.stream()
.map(request -> {
if (request.scheduleId() == null) {
return addSchedule(request, performance);
} else {
return updateSchedule(request, performance);
}
})
.collect(Collectors.toList());
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.
맞습니다 삭제를 먼저해야 위와 같은 불상사를 예방할 수 있습니다!
공연에 현재 존재하는 스케줄 ID 가져오기 -> 요청된 스케줄 ID 추출 -> 삭제할 스케줄 ID 결정(클라이언트 요청에 포함되지 않은 스케줄) -> 삭제할 스케줄 처리
의 순서로 회차를 삭제한 후 추가 및 업데이트 하도록 리팩토링 해두었습니다~
|
||
private List<ScheduleModifyResponse> processSchedules(List<ScheduleModifyRequest> scheduleRequests, Performance performance) { | ||
// 현재 존재하는 스케줄 ID를 가져옵니다. | ||
List<Long> existingScheduleIds = scheduleRepository.findIdsByPerformanceId(performance.getId()); |
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.
존재하는 id리스트를 existingScheduleIds에 저장한 후 비교 작업하는 아이디어 너무 좋네요!
schedule을 직접적으로 비교하지 않고 이렇게 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.
schedule 객체를 조회하는 쿼리는 전체 데이터를 메모리로 가져와서 전송해야 하므로 무거울 수 있지만, 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.
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.
볼륨이 큰 리팩토링 작업이었을텐데 정말 고생 많으셨습니다!!
꼼꼼한 log 처리, 테스트까지 최고입니다~
Related issue 🛠
Work Description ✏️
Trouble Shooting ⚽️
Related ScreenShot 📷
수정 시 공연 정보 GET 했을 때 현재 상태
회차, 등장인물, 스태프 수정 테스트1
Do
Assume
테스트 1 결과
회차, 등장인물, 스태프 수정 테스트2
Do
Assume
테스트 2 결과
회차 요청 시 만들어지는 회차가 3개 초과 시 에러처리
존재하지 않는 회차, 등장인물, 스태프 에러처리
해당 공연의 메이커가 아닐 경우 에러처리
예매자가 존재하지 않는데 가격을 동일하게 해서 요청
예매자가 존재하지 않는데 가격을 동일하게 해서 요청한 후 공연 정보 GET
예매자가 존재하지 않는데 가격을 다르게 해서 요청
예매자가 존재하지 않는데 가격을 다르게 해서 요청한 후 공연 정보 GET
예매 진행 후 isBookerExist true 확인
예매자가 존재하고 가격을 다르게 해서 요청
예매자가 존재하며, 가격을 다르게 해서 요청한 후 공연 정보 GET
예매자가 존재하고 가격을 동일하게 해서 요청
예매자가 존재하며, 가격을 동일하게 해서 요청한 후 공연 정보 GET
음수로 티켓 가격 업데이트시 예외처리
해당 공연에 속하지 않은 회차, 등장인물, 스태프를 수정하려고 할 때 에러처리
Uncompleted Tasks 😅
To Reviewers 📢