-
Notifications
You must be signed in to change notification settings - Fork 2
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
[BE] refactor/fix: 하이라이트 검증 객체 책임 이동, 하이라이트 삭제 로직 수정 #966
Conversation
Test Results156 tests ±0 153 ✅ ±0 4s ⏱️ -1s Results for commit 1ae78ed. ± Comparison against base commit 9b59f8d. This pull request removes 15 and adds 15 tests. Note that renamed tests count towards both.
♻️ This comment has been updated with latest results. |
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.
하나만 확인해줍쇼!
JOIN Answer a ON h.answerId = a.id | ||
JOIN Review r ON a.reviewId = r.id | ||
WHERE r.reviewGroupId = :reviewGroupId AND a.questionId = :questionId | ||
) |
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.
DELETE FROM Highlight h
WHERE h.answerId IN (
SELECT a.id FROM Answer a
JOIN Review r ON a.reviewId = r.id
WHERE r.reviewGroupId = :reviewGroupId AND a.questionId = :questionId
요것은 안될까용
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.
조인 하나 줄여버린 테드... 👏🏻
Set<Long> answerIds = answerRepository.findIdsByQuestionId(highlightsRequest.questionId()); | ||
highlightRepository.deleteAllByAnswerIds(answerIds); | ||
List<Long> requestedAnswerIds = highlightsRequest.getUniqueAnswerIds(); | ||
answerValidator.validateQuestionContainsAnswers(highlightsRequest.questionId(), requestedAnswerIds); |
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.
커밋이 잘 나눠져있어서 읽기 편했습니다!!😁
validator 삭제 & answer 로의 이동은 계속해서 말해왔던 것이기 때문에 쉽게 납득 & 이해할 수 있었어요!!
그런데 새로 만들어진 deleteByReviewGroupIdAndQuestionId
함수에 대해 테스트 코드 작성된게 없어 RC 드립니당~~
내가 하이라이트를 수정하면 다른 사람의 같은 질문 하이라이트가 사라집니다...
그리고 이건 정말로 그렇네요… 😱😱😱
아이고 이걸 왜 몰랐을까요 ㅠㅠㅠ
@Modifying | ||
@Query(""" | ||
SELECT h | ||
FROM Highlight h | ||
WHERE h.answerId IN :answerIds | ||
ORDER BY h.lineIndex, h.highlightRange.startIndex ASC | ||
DELETE FROM Highlight highlight WHERE highlight in ( | ||
SELECT h FROM Highlight h | ||
JOIN Answer a ON h.answerId = a.id | ||
JOIN Review r ON a.reviewId = r.id | ||
WHERE r.reviewGroupId = :reviewGroupId AND a.questionId = :questionId | ||
) |
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.
서브쿼리 vs exist 중에서 뭐가 더 성능이 좋을까 싶었는데
실행 계획을 보니 서브쿼리가 더 성능이 좋네요~ 굳굳👍
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.
바뀐 쿼리에 where 조건 컬럼들이 모두 인덱스가 적용되어있어서 괜찮겠네요👍👍
@RequiredArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class AnswerValidatorFactory { | ||
|
||
private final List<AnswerValidator> answerValidators; | ||
private final List<TypedAnswerValidator> validators; |
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.
이 클래스의 이름도 TypedAnswerValidatorFactory 로 바꿔줄 필요는 없을까요? 🤔
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.
반영했습니다 🛫
public interface TypedAnswerValidator { | ||
|
||
boolean supports(Class<? extends Answer> answerClass); | ||
|
||
void validate(Answer answer); | ||
} |
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.
저는 지난 PR(#958) 에서 AnwerMapper 를 추상 클래스로만들었어요!
그 이유는 AnswerMapper 와 이를 상속하는 CheckboxAnswerMapper 등이 is 관계라고 생각했으며, CheckboxAnswerMapper 가 다른 클래스를 상속할 일도 없기 때문에 굳이 인터페이스로 만들 필요가 없다고 생각하기 때문이에요.
저는 이런 관점에서 TypedAnswerValidator 도 추상 클래스가 되어야 한다고 생각하는데, 아루는 어떻게 생각하나요?
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.
is-a
, has-a
도 상속을 구분하는 하나의 방법이지만, 추상 클래스 또한 인터페이스에 비하면 구체화된 존재라고 할 수 있습니다. 구체 클래스보다는 인터페이스에 의존하는 게 더 유연할 것 같아서 이대로 두었어요.
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.
HighlightValidator가 하는 일이 Highlight과 무관합니다. 따라서 리뷰 그룹/답변을 검증하는 게 Highlight 패키지 아래에 있는 게 어색합니다.
와우.. 하이라이트에 필요한 검증이니까 당연히 highlightValidator에서 한다고 생각했는데, 이렇게 생각해볼 수 있었네요. 생각 포인트 하나 더 알고 갑니다😂
내가 하이라이트를 수정하면 다른 사람의 같은 질문 하이라이트가 사라집니다...
😱죄송합니다 여러분....ㅎㅎㅎㅎ 왜 눈치 못챘지..
단순 제안 하나있습니다!
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.
AnswerValidator라는 네이밍이 광범위하지 않나 싶어요.
추후에 어떤 역할이 여기에 추가될지 모른다는 걸 가정한다면 가능할수도 있겠지만,
현재는 question, reviewGroup에 해당하는 답변이 존재
하는지 확인하는 역할의 응집성을 갖고 있으니 AnswerExistenceValidator는 어떨까요?
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.
추후에 어떤 역할이 여기에 추가될지 모른다
저는 여기에 상당한 무게를 두었는데요, 개인적으로는 validator, mapper의 확장을 고려하고 있지 않습니다. 단지 매핑/검증용으로 나온 절차지향 중심 객체라고 생각해서요.
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.
validator, mapper를 대체하는 것을 고려한다면 여기가 최적의 장소가 되겠군요! 공감합니다~
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.
책임 책임 책임🥲🥲🥲 고민이 제일 어려웠는데 잘 바꿔줘서 배워갑니다...
7a33c4d
to
1ae78ed
Compare
rebase & force push했어요 |
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.
확인했습니다😊👍
HighlightValidator
의 역할을Answer
쪽으로 이동한다. #965🚀 어떤 기능을 구현했나요 ?
HighlightValidator
가 하는 일이Highlight
과 무관합니다. 따라서 리뷰 그룹/답변을 검증하는 게Highlight
패키지 아래에 있는 게 어색합니다. 처음에는 아래와 같은 두 가지 TODO를 만들었어요.🔥 어떻게 해결했나요 ?
AnswerValidator
는 타입별로 검증하는 기능을 제공하므로TypedAnswerValidator
라고 이름을 수정했습니다.AnswerValidator
에서 정답에 대한 검증을 수행하도록 책임을 부여했습니다.HighlightValidator
가 수행하던 두 가지 검증을 이곳에서 진행합니다.아래와 같이 JOIN을 활용해
reviewGroup
까지도 들어가 삭제하도록 합니다. 서브쿼리 있긴 한데, SELECT + DELETE와 같아서 추가 부하는 없을 것이라고 기대해요.📝 어떤 부분에 집중해서 리뷰해야 할까요?
Validator
삭제에 대한 근거가 확실한지 봐주세요.📚 참고 자료, 할 말
Validator
가 하나의 서비스 메서드에 묶여서 확장에 어려움을 겪는 경우가 몇군데 있습니다. 이걸 잘 풀어내서 재사용성을 높이면 좋겠어요.