-
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: 회원 추가로 인한 스키마 변경 #1075
Conversation
Test Results157 tests 154 ✅ 4s ⏱️ Results for commit 21a6ec3. ♻️ 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.
컨트롤러에서 커스텀 리졸버를 구현해서 Member를 받아온다고 가정하고 수정했습니다.
동의합니다 👍
리졸버를 사용해야 Session > JWT 로 바뀐다고 하더라도 변경이 적을 것 같네요
테드상의 고민이 많이 느껴진 코드였습니다🥹👏👏
몇가지 부분 코멘트 남겼습니다~
빨리 머지되는게 좋을 것 같아서, 별로이면 시원하게 "별로임 ㅋ" 남겨줘도 됩니다잉
@Column(name = "group_access_code", nullable = true) | ||
private String code; |
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에서 벗어나는 것 같고, 프론트와의 합의도 필요한 것이라 일단은 코멘트만 남겨놓습니다.
백로그로 생각해봅시다!
이슈 파뒀어요~ #1077
public String generateReviewRequestCode() { | ||
String reviewRequestCode; |
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 이어야 할 것 같아요~
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.
실수했네요.. 수정했습니다👍
@Slf4j | ||
public class GroupAccessCodeNullException extends NullPointerException{ | ||
public GroupAccessCodeNullException() { | ||
super("비회원 리뷰 그룹 생성은 그룹 액세스 코드를 필수로 입력해야 해요."); | ||
log.info("Non-member review group creation failed: Group access code is required"); | ||
} | ||
} |
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.
앞에 언급한 'reviewGroupAccessCode' 네이밍 변경의 필요성을 여기에서도 느꼈습니다..
예외 메시지가 한번에 이해되지 않네요😅
ALTER TABLE review_group ADD COLUMN member_id NULL; | ||
ALTER TABLE review_group MODIFY COLUMN group_access_code VARCHAR(255) 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.
member_id가 BIGINT라고 명시를 안해줘도 괜찮나요?
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.
앗 빼먹었군요 수정했습니다👍
@@ -11,18 +11,37 @@ | |||
class ReviewGroupTest { | |||
|
|||
@Test | |||
void 정상_생성된다() { | |||
void 회원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.
테스트 메서드가 직접적인 구현 내용을 포함하기보다,
"회원의 리뷰 그룹을 생성한다"와 같이 테스트 목적을 나타내게 하는건 어떨까요?
리뷰 그룹을 생성할 때 인자로 memberId 가 아니라 Member member 를 받게 한다면 깨질 테스트같네요.
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 Review(long templateId, long reviewGroupId, List<Answer> answers) { | ||
this(null, templateId, reviewGroupId, answers); | ||
} | ||
|
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을 파기보다 이 PR에서 추가 커밋으로 작업하는건 어떤가요?
그것까지 포함해야 Review 에 member 라는 개념이 추가되었다고 볼 수 있을 것 같아서요!
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을 계속 사용하거나, 의미 없는 memberId를 명시하자니, 가독성이 너무 떨어지게 되어서 차라리 생성자를 나누면 확실하게 회원/비회원이 작성한 리뷰임을 생성했다고 알 수 있을 것 같아서 그냥 두었어요.
근데 역시 테스트 전용이라는 딱지가 붙는 것 같아 찝찝하네요. 😭👍
차라리 테스트코드에서만 생성자를 나눠서 사용할 수 있도록 ReviewFixture를 두어서 적용해봤습니다!
@PostMapping("/v2/reviews") | ||
public ResponseEntity<Void> createReview(@Valid @RequestBody ReviewRegisterRequest request) { | ||
// 회원 세션 추후 추가해야 함 | ||
long savedReviewId = reviewRegisterService.registerReview(request); | ||
public ResponseEntity<Void> createReview( | ||
@Valid @RequestBody ReviewRegisterRequest request | ||
/* | ||
TODO: 회원 세션 임시 사용 방식, 이후 리졸버를 통해 객체로 받아와야 함 | ||
@Nullable @LoginMember Member member | ||
*/ | ||
) { | ||
/* | ||
TODO: 회원 세션 유무에 따른 분기처리 로직 | ||
Long memberId = Optional.ofNullable(member).map(Member::getId).orElse(null); | ||
*/ | ||
long memberId = 1L; // 임시 | ||
long savedReviewId = reviewRegisterService.registerReview(request, memberId); |
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 를 컨트롤러에서 인자로 받고,
Long memberId = Optional.ofNullable(member).map(Member::getId).orElse(null);
를 주석 해제하는건 어떤가요?
이 코드대로라면 dev 서버에서 리뷰를 작성했을 때, 나중에 정합성 문제가 생길 것 같아요.
dev 서버긴 하더라도 나중에 귀찮을 일은 안만드는게 좋다 생각합니다 🙋🏻♀️
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가 구현되어 있지 않아서 주석 처리 했습니다.
일단은 빠르게 머지하기 위해서 null을 전달하는 것으로 수정 하고 리졸버와 함께 바로 작업예정입니다~
public Review(Long memberId, long templateId, long reviewGroupId, List<Answer> answers) { | ||
this.memberId = memberId; | ||
this.templateId = templateId; | ||
this.reviewGroupId = reviewGroupId; | ||
this.answers = answers; | ||
this.createdAt = LocalDateTime.now(); | ||
} |
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 이 될 수 있는 memberId 는 생성자에서 인자 순서를 맨 뒤로 하는게 어떨까요?
별로면 "별로임"이라고 남겨주세요!
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을 전달하는 경우는 없으니, 필드 순서와 생성자 순서를 맞추는 것이 가독성이 더 좋다고 생각합니다..🙏
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.
추가로, @nullable을 명시해서 null이 올 수 있다는 것을 명시했어요!
/* | ||
TODO: 회원 세션 임시 사용 방식, 이후 리졸버를 통해 객체로 받아와야 함 | ||
@Nullable @LoginMember Member member | ||
*/ | ||
) { |
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.
Ditto ~
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 ReviewGroup(Long memberId, long templateId, String reviewee, String projectName, String reviewRequestCode) { | ||
this(memberId, templateId, reviewee, projectName, reviewRequestCode, null); | ||
} | ||
|
||
public ReviewGroup(long templateId, String reviewee, String projectName, String reviewRequestCode, | ||
String groupAccessCode) { | ||
this(null, templateId, reviewee, projectName, reviewRequestCode, groupAccessCode); | ||
} |
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.
개인적으로 Review 등록 코드를 감명깊게 봤어요.
nullable 에 대한 특별한 처리 없이 Long memberId 를 넘겨주는게 깔끔하더라고요.
그래서 ReviewGroup 코드에서는 왜 이 방식으로 하지 않았지? 싶었어요.
public ReviewGroup(long templateId, String reviewee, String projectName, String reviewRequestCode,
@Nullable Long memberId, @Nullable String groupAccessCode) {
validateRevieweeLength(reviewee);
validateProjectNameLength(projectName);
validateMemberIdOrGroupAccessCode(memberId, groupAccessCode);
this.memberId = memberId;
this.templateId = templateId;
this.reviewee = reviewee;
this.projectName = projectName;
this.reviewRequestCode = reviewRequestCode;
}
private void validateMemberIdOrGroupAccessCode(Long memberId, String groupAccessCode) {
if ((memberId != null && groupAccessCode != null) || (memberId == null && groupAccessCode == null)) {
throw new IllegalArgumentException("Either memberId or groupAccessCode must be 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.
Review는 단순히 작성자가 있느냐 없느냐 이 차이라서 상관없었지만, ReviewGroup에서는 memberId가 있으면 groupAccessCode가 존재하면 안된다는 것을 검증하는 것이 ReviewGroup 자체 도메인과는 별개로 회원 정책에 관여하다고 느껴서 서비스에서 분기처리 하는 것으로 구현했어요.
리뷰 그룹은 말 그대로 리뷰를 묶어서 관리하는 그룹인데 이 그룹이 회원 전용인지, 비회원 전용인지에 대한 개념 자체가 리뷰 그룹의 책임인가? 라고 볼 수 없을 것 같아요. 즉, 리뷰 그룹이라는 개념은 회원 전용/비회원 전용이라는 개념이 없어도 존재할 수 있는 도메인이예요. 따라서 우리가 리뷰 그룹이 Member를 몰라도 된다고 생각해서 간접 참조를 사용했는데 이를 검증하는 로직이 내부에 있다면 맞지 않다고 생각했어요.
반면 리뷰의 memberId는 말 그대로 작성자가 있냐 없냐의 개념이어서 단순히 데이터를 가지고 있기 때문에 어색함이 없어요.
해당 코멘트로 인해 조금 더 생각해보니, 리뷰 그룹에서 생성자를 나눠놓은 것 자체가 어느정도 책임을 가지고 있다는 생각이 드네요.
산초의 이 리뷰가 아니었다면 의도와 맞지 않는 코드가 될 뻔했네요. 👍👍
일단 정해진 기능 구현이 우선이니, 이 부분은 조금 더 생각해서 리팩터링 해보겠습니다. 🙏
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.
선프루브! 후팩터링!
Deploying 2024-review-me-release with
|
Latest commit: |
5a4da23
|
Status: | ✅ Deploy successful! |
Preview URL: | https://e2286523.2024-review-me-release.pages.dev |
Branch Preview URL: | https://be-refactor-1074-schema-chan.2024-review-me-release.pages.dev |
Deploying 2024-review-me-develop with
|
Latest commit: |
5a4da23
|
Status: | ✅ Deploy successful! |
Preview URL: | https://e17f094d.2024-review-me-develop.pages.dev |
Branch Preview URL: | https://be-refactor-1074-schema-chan.2024-review-me-develop.pages.dev |
9ce224a
to
5a4da23
Compare
🚀 어떤 기능을 구현했나요 ?
회원 기능이 추가되면서 일부 엔티티에 memberId가 필요하게 되었습니다.
🔥 어떻게 해결했나요 ?
📝 어떤 부분에 집중해서 리뷰해야 할까요?
📚 참고 자료, 할 말