-
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] feat: 리뷰 폼 응답 재구현 #295
Conversation
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 final TemplateService templateService; | ||
|
||
@GetMapping("/reviews/write") |
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.
기존 컨트롤러 지우면 프론트엔드가 간극이 있을 수 있으니 버전 업 하는 게 좋을 듯해요. v2
prefix를 들고가보는 건 어떨까요 /
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.
(이미 반영되었네요)
OptionGroupResponse optionGroup, | ||
boolean hasGuideline, | ||
String guideline |
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.
null할 수 있는건 response단에서 @Nullable
명시해주는 건 어떤가요 ?
@@ -7,7 +7,7 @@ | |||
public class InvalidAnswerLengthException extends BadRequestException { | |||
|
|||
public InvalidAnswerLengthException(int answerLength, int minLength, int maxLength) { | |||
super("답변의 길이는 %d자 이상 %d자 이하여야 합니다.".formatted(minLength, maxLength)); | |||
super("답변의 길이는 %d자 이상 %d자 이하여야 해요.".formatted(minLength, maxLength)); | |||
log.info("AnswerLength is out of bound - answerLength:{}, minLength: {}, maxLength: {}", |
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.info("AnswerLength is out of bound - answerLength:{}, minLength: {}, maxLength: {}", | |
log.info("AnswerLength is out of bound - answerLength: {}, minLength: {}, maxLength: {}", |
public boolean hasGuideline() { | ||
return !guideline.isEmpty(); | ||
} |
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.
guideline이 nullable해서, 체크할 필요도 있습니다! 이거 추가로 테스트도 작성해야겠네요
|
||
public NoRegisteredTemplatesException() { | ||
super("서버 내부에서 문제가 발생했어요. 서버에 문의해주세요."); | ||
log.warn("NoRegisteredTemplatesException is occurred"); |
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 SectionNotFoundException(long id) { | ||
super("서버 내부에서 문제가 발생했어요. 서버에 문의해주세요."); | ||
log.info("SectionNotFoundException is occurred - id: {}", 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.
문의 바람은 warn
이 낫겠네요!
@Repository | ||
public interface TemplateRepository extends JpaRepository<Template, Long> { | ||
|
||
Optional<Template> findTopByOrderByIdDesc(); |
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로 찾는 게 더 낫지 않나요? 나중에 여러 개가 들어오면 확장하기 어려울 것 같아요
List<SectionResponse> sectionResponses = template.getSectionIds() | ||
.stream() | ||
.map(this::mapToSectionResponse) | ||
.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.
섹션 하나당 쿼리가 한 개 나갈텐데, 레포에서 쿼리 묶어서 하는 게 더 효율은 좋겠습니다. 일단 구현이 급선무니 이건 넘어가도 좋아요
if (!tableName.equals("section_ids") && !tableName.equals("question_ids")) { | ||
entityManager.createNativeQuery(ALTER_FORMAT.formatted(tableName)).executeUpdate(); | ||
} |
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.
이..건 일대다 단방향을 맺는 게 나아보입니다 ㅋㅋㅋ
@@ -19,7 +19,7 @@ public class TemplateService { | |||
private final TemplateRepository templateRepository; | |||
private final TemplateMapper templateMapper; | |||
|
|||
@Transactional | |||
@Transactional(readOnly = 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.
dto의 content까지 검증하지 않아도 된다고 생각해요~
코멘트 남긴 것 정도(객관식, 주관식일 때의 각각 null)만 더 검증이 있으면 된다고 생각합니다!
수고수고쓰~~
OptionGroupResponse optionGroupResponse = optionGroupRepository.findByQuestionId(question.getId()) | ||
.map(this::mapToOptionGroupResponse) | ||
.orElse(null); | ||
|
||
return new QuestionResponse( | ||
question.getId(), | ||
question.isRequired(), | ||
question.getContent(), | ||
question.getContent(), | ||
optionGroupResponse, |
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.
Optional로 null 가능성을 명시하면서 안전성을 챙기는 건 어떨까요?
OptionGroupResponse optionGroupResponse = optionGroupRepository.findByQuestionId(question.getId()) | |
.map(this::mapToOptionGroupResponse) | |
.orElse(null); | |
return new QuestionResponse( | |
question.getId(), | |
question.isRequired(), | |
question.getContent(), | |
question.getContent(), | |
optionGroupResponse, | |
Optional<OptionGroupResponse> optionGroupResponse = optionGroupRepository.findByQuestionId(question.getId()) | |
.map(this::mapToOptionGroupResponse); | |
return new QuestionResponse( | |
question.getId(), | |
question.isRequired(), | |
question.getContent(), | |
question.getContent(), | |
optionGroupResponse.orElse(null), | |
); |
ReviewGroupRepository reviewGroupRepository; | ||
|
||
@Test | ||
void 리뷰_그룹과_템플릿으로_템플릿_응답을_매핑한다() { |
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.
QuestionResponse 매핑시 optionGroup이 없으면 null로 들어가는 로직 등이 있기때문에 이에 대한 테스트가 필요하다고 생각해요!
현제 테스트에 주관식 섹션을 추가해서 optionGroup은 null로 들어간 것을 검증하는 형식으로요!
private QuestionResponse mapToQuestionResponse(long questionId) {
Question2 question = questionRepository.getQuestionById(questionId);
OptionGroupResponse optionGroupResponse = optionGroupRepository.findByQuestionId(question.getId())
.map(this::mapToOptionGroupResponse)
.orElse(null);
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.
(급한 건 아닙니다! 얘기해볼 점!)
Mapper를 쓰니 서비스가 깔끔해서 보기 좋은데 현재 수준에서 Mapper로 분리가 필요한 정도는 아니지 않을까?하는 의견입니다!
지금 생각으로는 TemplateService에 더 들어올 로직이 떠오르는 게 없는데, 그렇다면 현재 TemplateSevice는 곧 템플릿 생성이라는 역할만을 전적으로 담당하는 서비스인데, Mapper가 그 생성을 다시 한 번 나눠가진 느낌이 들어요.
(별개로 더 복잡해지는 경우 응집도를 위해서 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.
코멘트로 남겨서 RC 추가!
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.
제가 작성하는 코드 스타일과 비슷한 것 같네요 ㅋㅎㅎ
별로 코멘트 남길게 없습니당!
그리고 ElementCollection 에 Fetch EGAGER 을 해주신 것은 저도 필요성을 느끼긴 했었는데,
ElementCollection 을 사용하는 것 자체에 대해서 괜찮은 방법이었을지 의구심이 들긴 하네요
여러 PR을 읽으면서 느낀 점입니다. (특히 아루의 조회 PR)
일단 리뷰 반영하면서 더 생각해보기로 해요!
Template defaultTemplate = templateRepository.findTopByOrderByIdDesc() | ||
.orElseThrow(NoRegisteredTemplatesException::new); |
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.
ReviewGroup에 templateId 필드를 두고, 거기로부터 templateId 를 가져와서 조회하는게 좋을 것 같아요! (지금은 templateId 가 review에 있는데 개인적으로 ReviewGroup에 옮겨야 한다고 생각합니다)
public TemplateResponse mapToTemplateResponse(ReviewGroup reviewGroup, Template template) { | ||
List<SectionResponse> sectionResponses = template.getSectionIds() | ||
.stream() | ||
.map(this::mapToSectionResponse) | ||
.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.
ㅋㅋㅋㅋㅋ 연쇄매핑마.. 그래도 보기 깔끔해서 좋네요!
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 reviewme.template.dto.response.TemplateResponse; | ||
import reviewme.template.repository.TemplateRepository; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class TemplateService { | ||
|
||
private static final Long USE_TEMPLATE_ID = 1L; |
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.
널러블하지 않으니 long
으로 가시죠!
…at/286-review-creation-setup # Conflicts: # backend/src/main/java/reviewme/question/domain/OptionItem.java # backend/src/main/java/reviewme/question/domain/Question2.java # backend/src/main/java/reviewme/question/repository/OptionGroupRepository.java # backend/src/main/java/reviewme/question/repository/OptionItemRepository.java # backend/src/main/java/reviewme/question/repository/Question2Repository.java # backend/src/main/java/reviewme/template/domain/Section.java # backend/src/main/java/reviewme/template/domain/Template.java # backend/src/main/java/reviewme/template/domain/exception/SectionNotFoundException.java # backend/src/main/java/reviewme/template/repository/SectionRepository.java # backend/src/main/java/reviewme/template/repository/TemplateRepository.java
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.
리프룹
🚀 어떤 기능을 구현했나요 ?
🔥 어떻게 해결했나요 ?
📝 어떤 부분에 집중해서 리뷰해야 할까요?
TemplateMapperTest
의리뷰_그룹과_템플릿으로_템플릿_응답을_매핑한다
테스트에서 문제가 발생하고 있습니다.TemplateMapper.mapToSectionResponse()
메서드 내부에서sectionRepository.getSectionById(sectionId)
부분이 실행될 때, 갑자기 section에 저장된 questionId 가 동일한 id로 한번 더 저장된 채 반환되고 있습니다. (디버깅 했지만 이유를 찾지 못했습니다.)📚 참고 자료, 할 말