-
Notifications
You must be signed in to change notification settings - Fork 4
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] 투표 도메인 리팩터링 #727
base: dev
Are you sure you want to change the base?
Changes from all commits
3c78b11
91bb5aa
def5a4f
1f91424
7735524
0f56c56
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,12 +6,11 @@ | |
@Getter | ||
public enum VoteExceptionType implements ExceptionType { | ||
|
||
CANNOT_VOTE_MY_POST(700, "해당 게시글 작성자는 투표할 수 없습니다."), | ||
CANNOT_VOTE_MY_POST(700, "게시글 작성자는 투표할 수 없습니다."), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍👍 |
||
NOT_FOUND(701, "참여한 투표가 존재하지 않습니다."), | ||
ALREADY_VOTED(702, "이미 참여한 투표입니다."), | ||
; | ||
|
||
|
||
private final int code; | ||
private final String message; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,15 +34,37 @@ public void vote( | |
final Post post = postRepository.findById(postId) | ||
.orElseThrow(() -> new NotFoundException(PostExceptionType.NOT_FOUND)); | ||
|
||
validateAlreadyVoted(member, post); | ||
|
||
final PostOption postOption = postOptionRepository.findById(postOptionId) | ||
.orElseThrow(() -> new NotFoundException(PostOptionExceptionType.NOT_FOUND)); | ||
|
||
final Vote vote = post.makeVote(member, postOption); | ||
validateAlreadyVoted(member, post); | ||
final Vote vote = createVote(member, post, postOption); | ||
voteRepository.save(vote); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분은 생략해도 변경 감지에 의해 vote가 자동으로 insert 될 것 같아요 |
||
} | ||
|
||
private Vote createVote(final Member member, final Post post, final PostOption postOption) { | ||
validateDeadline(post); | ||
validatePostOption(post, postOption); | ||
Comment on lines
+46
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 숨겨진 게시글에 대한 검증도 있으면 좋을 것 같아요 ㅎㅎ |
||
|
||
final Vote vote = Vote.builder() | ||
.member(member) | ||
.postOption(postOption) | ||
.build(); | ||
postOption.addVote(vote); | ||
return vote; | ||
Comment on lines
+49
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. createVote메서드에선 postOption 셋팅을 제외한 Vote를 만드는 로직만 남겨두고, 양방향 관계를 맺어주는 건 이미 postOption.addVote(vote) 여기서 해주고 있으니 차라리 밑의 예시처럼 구현하는 것은 어떨까요? private Vote createVote(final Member member) {
return Vote.builder()
.member(member)
.build();
} 그리고 vote 메서드에서 postOption.addVote(vote); 이 코드를 진행하는 형식입니다. createVote 메서드의 파라미터 수도 줄일 수 있고, 코드의 흐름을 파악하기 더 수월할 것 같아요 :) |
||
} | ||
|
||
private void validatePostOption(final Post post, final PostOption postOption) { | ||
if (!post.hasPostOption(postOption)) { | ||
throw new BadRequestException(PostOptionExceptionType.NOT_FOUND); | ||
} | ||
} | ||
|
||
private void validateDeadline(final Post post) { | ||
if (post.isClosed()) { | ||
throw new BadRequestException(PostExceptionType.CLOSED); | ||
} | ||
} | ||
|
||
private void validateAlreadyVoted(final Member member, final Post post) { | ||
final List<PostOption> postOptions = post.getPostOptions(); | ||
|
@@ -72,8 +94,8 @@ public void changeVote( | |
.orElseThrow(() -> new NotFoundException(PostOptionExceptionType.NOT_FOUND)); | ||
|
||
voteRepository.delete(originVote); | ||
final Vote vote = post.makeVote(member, newPostOption); | ||
voteRepository.save(vote); | ||
final Vote newVote = createVote(member, post, newPostOption); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분도 위의 리뷰 내용과 동일하게 적용 될 것 같습니다. |
||
voteRepository.save(newVote); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.votogether.domain.vote.entity; | ||
|
||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
import com.votogether.domain.member.entity.Member; | ||
import com.votogether.domain.post.entity.Post; | ||
import com.votogether.domain.post.entity.PostOption; | ||
import com.votogether.global.exception.BadRequestException; | ||
import java.time.LocalDateTime; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.test.util.ReflectionTestUtils; | ||
|
||
class VoteTest { | ||
|
||
@Test | ||
@DisplayName("게시글 작성자가 투표를 하면 예외가 발생한다.") | ||
void voteException() { | ||
// given | ||
Member writer = Member.builder().nickname("글쓴이").build(); | ||
ReflectionTestUtils.setField(writer, "id", 1L); | ||
Post post = Post.builder().title("제목").content("내용").deadline(LocalDateTime.now()).writer(writer).build(); | ||
PostOption postOption = PostOption.builder().post(post).content("내용").build(); | ||
|
||
// when, then | ||
assertThatThrownBy(() -> Vote.builder().member(writer).postOption(postOption).build()) | ||
.isInstanceOf(BadRequestException.class) | ||
.hasMessage("게시글 작성자는 투표할 수 없습니다."); | ||
} | ||
|
||
} |
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.
생성자에게 꼼꼼한 검증은 좋은 방법이라고 생각합니다 👍
한 가지 우려되는 점은
Vote
에서Post
의존성을 가지게 되면 Vote -> Post -> PostOption -> Vote의 순환 참조가 발생할 수 있는 위험이 증가한다고 생각이 들어요.따라서 해당 검증은
Service
계층의 비즈니스 로직에서 처리하는게 어떤지 물어보고 싶어요 :)