Skip to content
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

[Feature] 리뷰 진행하기 #24

Merged
merged 14 commits into from
Oct 28, 2024
Merged

Conversation

heejjinkim
Copy link
Collaborator

@heejjinkim heejjinkim commented Oct 24, 2024

✏️ Description

  • 주관식 질문 추가
  • 리뷰 폼 질문들 반환 api
  • 리뷰 임시저장 api
  • 리뷰 제출하기 api

🙏🏻 To Reviewers

  • ReviewRecord가 리뷰폼에 대해 리뷰어가 답변한 데이터입니다.
    • 주관식 답변, 객관식 답변 모두 CRUD가 한번에 일어나므로 각각 하나의 json형태의 필드로 넣었습니다. 각 개별 질문에 대한 답변을 다루는 일은 아마 없다고 생각합니다.
    • 객관식 답변은 명함을 제작하기 위해 필요하지만, 주관식 답변은 필요 없기 때문에 두 개도 분리했습니다.
  • 리뷰 폼 질문들 반환 api
    • 리뷰하기를 시작할 때 사용되는 api입니다.
    • 이전에 임시저장한 답변 데이터가 있으면, 이를 같이 반환합니다.
  • 리뷰 임시저장 api
    • 리뷰를 진행하다가 임시저장 버튼을 누르면 호출되는 api 입니다.
    • 처음 임시저장일 경우, ReviewRecord를 생성하여 저장합니다.
    • 이미 임시저장을 했을 경우, 기존 ReviewRecord를 조회해와 수정합니다.
    • [POST]첫 임시저장 api와 [PATCH]그 이후의 임시저장 api를 처음에 분리할까 고민했지만.. 그렇게 하면 프론트에서 너무 복잡할 것 같아 하나의 api로 만들었습니다.
  • 리뷰 제출하기 api
    • 리뷰를 다 하고 최종적으로 제출할 때 호출되는 api 입니다.
    • 이미 저장된 ReviewRecord가 있으면 조회해와 수정하고, 그렇지 않으면 새로 생성해 저장합니다.
    • 마찬가지로 Post와 Patch를 구분해야 하나 고민했지만.. 그럼 임시저장, 제출하기 api 2개가 무려 api 4개로 증가해서 구분하지 않았습니다.
  • Dto 정적 팩토리 메서드 of 에 대해
    • OptionDto, QuestionResponse 등등을 보시면 제가 상황에 따른 of 메서드를 여러개 만들어두었습니다. dto를 최대한 재활용하고 싶은 마음에 저런 식으로 of 메서드가 늘어나게 되었는데, 막상 저렇게 하고 나니 dto 클래스 내부가 너무 복잡해진 것 같다는 생각이 드네요..
    • 그래서 생각나는 방향성은
      • 지금 상태 유지(of 메서드 여러 개)
      • of 메서드를 하나만 가지도록 상황에 따른 dto를 여러개 만들기
      • QuestionResponse 관련된 dto들에 대한 생성 담당은 따로 Converter 클래스를 만들기
    • 저는 이미 제 코드에 익숙해져버려서..ㅜㅜ 딱 처음 봤을 때 너무 복잡한 것 같은지 민제님 의견이 궁금합니다🙏

💡 Issue Number

@heejjinkim heejjinkim self-assigned this Oct 24, 2024
@heejjinkim heejjinkim added the ✨ feature New feature or request label Oct 24, 2024
@heejjinkim heejjinkim requested a review from minje0204 October 24, 2024 17:01
.orElseGet(() -> ReviewRecord.of(writer, reviewForm, request));
}

private Member findMemberById(Long memberId) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review도메인과는 관련이 없는 메소드인 것 같아서 MemberService를 DI 받아서 사용하는 방식은 어떠신가요?

findById는 다른 곳에서도 많이 사용될 것 같은데, 멤버를 찾지 못해서 발생하는 예외사항 처리도 멤버 서비스에서 해주고, Review Service에서는 아예 신경쓰지 않으면 Review도메인이라는 관심사에 조금더 집중이 될 것 같아요.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

밑에 다른 비공개 메서드들도 보다보니, 다른 서비스를 주입받아 사용할 메서드와 서비스 내부적으로 레포지토리에 직접 접근해서 데이터를 가져오는(위 코멘트 방식) 기준이 애매하겠네요...

무시해주셔도 될 것 같아요~!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 말씀하셨던 Repository에서 예외처리도 해주는 방식으로 수정해보겠습니다.
https://ttl-blog.tistory.com/1467

request.getReviewFormId())
);
memberIdList.forEach(reviewerId -> {
findMemberById(reviewerId);
Copy link
Collaborator

@minje0204 minje0204 Oct 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findMemberById의 목적이 2가지로 사용되고 있는 것 같은데 맞을까요?

  • ID에 해당하는 멤버 인스턴스 Return
  • ID에 해당하는 멤버가 있는지 Validation

기존 메서드 이름은 Validation하는 목적이 포함이 안되어 있는 것 같아서
두가지 목적으로 같이 사용하신다면 findMemberByIdOrElseThrow() 나 너무 길게 느껴지신다면 findMemberOrElseThrow()는 어떠신가요?

후자의 경우 파라미터로 넘어가는 memberId로 Id로 멤버를 찾는다는 것이 명시적인 것 같아서 생략해도 되지 않나 싶어서요

Copy link
Collaborator

@minje0204 minje0204 Oct 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alarmService에서 reviewId에 대한 유효성 검사를 하고 있는 것 같은데, 더블체크를 위해 추가해주신걸까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alarmService에서 reviewId에 대한 유효성 검사를 하고 있는 것 같은데, 더블체크를 위해 추가해주신걸까요?

alarmService에서 reviewId 유효성 검사하는 로직이 있다는 것을 까먹었네요.. ReviewService의 유효성 검사용 findMemberById는 지우도록 하겠습니다


Member writer = findMemberById(memberId);
ReviewForm reviewForm = findReviewFormById(reviewFormId);
ReviewRecord reviewRecord = getOrCreateReviewRecord(writer, reviewForm, request);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

깔끔한 extract method군요 👍 👍

savedRecord.update(request);
return savedRecord;
})
.orElseGet(() -> ReviewRecord.of(writer, reviewForm, request));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

람다식 안에 if문이 들어가 있어서 이부분도 extract Method를 해주면 좋을 것 같네요! 비공개 메서드가 좀 많아 지는군요

private ReviewRecord getOrCreateReviewRecord(Member writer, ReviewForm reviewForm, ReviewSaveRequest request) {
    return reviewRecordRepository.findByReviewForm(reviewForm)
        .map(savedRecord -> updateIfDraft(savedRecord, request))
        .orElseGet(() -> ReviewRecord.of(writer, reviewForm, request));
  }

  private ReviewRecord updateIfDraft(ReviewRecord savedRecord, ReviewSaveRequest request) {
    validateIfAlreadySubmitted(savedRecord);
    savedRecord.update(request);
    return savedRecord;
  }

  private void validateIfAlreadySubmitted(ReviewRecord savedRecord) {
    if (!savedRecord.getIsDraft()) {
      throw new RestApiException(ReviewErrorCode.ALREADY_SUBMITTED);
    }
  }

private List<ChoiceQuestion> findChoiceQuestionsByCategories(List<CategoryType> categoryTypes) {

return categoryTypes.stream()
.flatMap(category -> choiceQuestionRepository.findByCategoryType(category)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 잘 몰라서 그러는 것 같은데 카테고리별로 질문들을 따로 분리 안해도 괜찮나요?

[
"협업": [협업관련 질문리스트],
"커뮤니케이션": [...],
...
]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

분리해야하는 거 맞습니다..! 확인해보니 지금 코드에서 flatMap을 써서 모든 카테고리 질문들을 하나로 합친 다음에, Response를 만들 때 groupby로 카테고리별로 다시 묶고있네요.. 수정하겠습니다

Copy link
Collaborator

@minje0204 minje0204 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다~!

기존 코드는 flatMap 사용 후 grouping 수행
카테고리별 질문들을 처음부터 분리하도록 Map 사용

related to: #18
@heejjinkim heejjinkim merged commit 3c06dc0 into develop Oct 28, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants