-
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
[BE] 서비스 중복 로직 제거 및 캡슐화 #724
Changes from all commits
560d1c5
0d32863
d8983f9
52770a7
d24537a
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 |
---|---|---|
@@ -1,10 +1,12 @@ | ||
package harustudy.backend.participant.domain; | ||
|
||
import harustudy.backend.auth.exception.AuthorizationException; | ||
import harustudy.backend.common.BaseTimeEntity; | ||
import harustudy.backend.content.domain.Content; | ||
import harustudy.backend.member.domain.Member; | ||
import harustudy.backend.participant.exception.NicknameLengthException; | ||
import harustudy.backend.participant.exception.ParticipantIsNotHostException; | ||
import harustudy.backend.participant.exception.ParticipantNotBelongToStudyException; | ||
import harustudy.backend.study.domain.Study; | ||
import jakarta.persistence.CascadeType; | ||
import jakarta.persistence.Entity; | ||
|
@@ -95,4 +97,16 @@ public void validateIsHost() { | |
throw new ParticipantIsNotHostException(); | ||
} | ||
} | ||
|
||
public void validateIsBelongsTo(Study study) { | ||
if (!this.study.getId().equals(study.getId())) { | ||
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. 좋은 아티클 추천 감사합니다 마코! 덕분에 잊고 지내던 동등성에 대해서 다시 한 번 생각할 수 있게 되었네요 ㅎㅎ Study 엔티티에서 id를 제외하면 다른 필드를 가지고 Study 엔티티를 고유하게 판단할 수 있는 기준으로 잡을 수 있는 비즈니스 키를 도출하기 어렵겠다는 데는 같은 생각입니다. 같은 이유로 PK 이외의 필드들로 엔티티의 고유성을 부여하는 것도 어려우니, 선택지가 PK밖에 없을 것 같아요. 사실 Set과 같은 컬렉션을 사용할 때 해당 자료구조의 동작 원리가 깨질 수 있다는 건 비영속화된 엔티티를 영속화된 엔티티와 함께 사용하기 때문이라고 생각해요. 그리고 비영속화된 엔티티를 비즈니스 로직을 처리하는데 사용해야 된다고 한다면 VO로서 사용되어야 한다는 입장입니다. 엔티티와 VO로 나누어 생각한다면 이들을 함께 컬렉션에 담아 사용하지는 않을 것 같아요! 저희가 프로젝트 리팩토링의 방향을 좀 더 객체지향스러운 쪽으로 진행하고자 한다면 마코가 제시해주신 방향대로 구현하는게 맞을 것 같아요. 추후 저희가 컬렉션을 사용해야 하는 상황이 온다면 VO로 변환해서 해당 로직을 수행하도록 하면 될 것이고요. 몇달 전에 했었던 지하철 미션이 생각나네요 ㅎㅎ... 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. 오 오랜만에 레벨1의 영광을 다시 느끼는 기분이군요..👍 말씀해주신대로 id 값을 기준으로 동등성을 비교하느냐 내부 필드를 기준으로 동등성을 비교하느냐는 객체의 성격에 따라 나뉠 거 같습니다! 제 기억으로는 코드 곳곳에 이런 동등성 비교가 id로 이루어졌던 것 같아 개편이 필요하긴 한 것 같습니다. 개인적으로는 조만간 도메인 격벽 분리 & 이벤트로 의존성 개선을 해야 할 것 같은데 해당 이슈 미리 파두고 한번에 개선하면 좋을 것 같은데 어떻게 생각하시나요? 만약 이번 PR에서 개선해야 한다면 추가적인 논의가 필요한 것 같은데, 이는 만나서 이야기해봐야 할 것 같네요! 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. 위에 polling 관련 메서드 네이밍 관련한 이슈도 그렇고 따로 PR을 만들어 거기에서 해결해보는 방향이 좋겠네요! 일단 이슈 먼저 파뒀습니다! |
||
throw new ParticipantNotBelongToStudyException(); | ||
} | ||
} | ||
|
||
public void validateIsCreatedByMember(Member member) { | ||
if (isNotCreatedBy(member)) { | ||
throw new AuthorizationException(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,21 +5,16 @@ | |
import harustudy.backend.member.domain.Member; | ||
import harustudy.backend.member.repository.MemberRepository; | ||
import harustudy.backend.participant.domain.Participant; | ||
import harustudy.backend.participant.domain.Step; | ||
import harustudy.backend.participant.dto.ParticipateStudyRequest; | ||
import harustudy.backend.participant.dto.ParticipantResponse; | ||
import harustudy.backend.participant.dto.ParticipantsResponse; | ||
import harustudy.backend.participant.exception.ParticipantNotBelongToStudyException; | ||
import harustudy.backend.participant.dto.ParticipateStudyRequest; | ||
import harustudy.backend.participant.exception.ParticipantNotFoundException; | ||
import harustudy.backend.participant.repository.ParticipantRepository; | ||
import harustudy.backend.study.domain.Study; | ||
import harustudy.backend.study.exception.StudyAlreadyStartedException; | ||
import harustudy.backend.study.repository.StudyRepository; | ||
import jakarta.annotation.Nullable; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
|
@@ -33,32 +28,31 @@ public class ParticipantService { | |
private final StudyRepository studyRepository; | ||
|
||
@Transactional(readOnly = true) | ||
public ParticipantResponse findParticipant( | ||
AuthMember authMember, Long studyId, Long participantId | ||
) { | ||
public ParticipantResponse findParticipant(AuthMember authMember, Long studyId, Long participantId) { | ||
Study study = studyRepository.findByIdIfExists(studyId); | ||
Participant participant = participantRepository.findByIdIfExists(participantId); | ||
validateParticipantIsRelatedWith(participant, authMember, study); | ||
Member member = memberRepository.findByIdIfExists(authMember.id()); | ||
|
||
participant.validateIsCreatedByMember(member); | ||
participant.validateIsBelongsTo(study); | ||
|
||
return ParticipantResponse.from(participant); | ||
} | ||
|
||
// TODO: 임시용이므로 이후에 제거 | ||
public ParticipantsResponse tempFindParticipantWithFilter( | ||
AuthMember authMember, Long studyId, Long memberId | ||
) { | ||
@Transactional(readOnly = true) | ||
public ParticipantsResponse tempFindParticipantWithFilter(AuthMember authMember, Long studyId, Long memberId) { | ||
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. 요거 temp 메서드 왜 생겼었는지 또 기억이 안나네요 ㅎㅎ... 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. 오 여기 readonly가 빠졌었네요! 굿굿 바로 변경했습니다! |
||
Study study = studyRepository.findByIdIfExists(studyId); | ||
if (Objects.isNull(memberId)) { | ||
validateEverParticipated(authMember, study); | ||
return getParticipantsResponseWithoutMemberFilter(study); | ||
} | ||
Member member = memberRepository.findByIdIfExists(memberId); | ||
validateIsSameMemberId(authMember, memberId); | ||
Member member = memberRepository.findByIdIfExists(memberId); | ||
return tempGetParticipantsResponseWithMemberFilter(study, member); | ||
} | ||
|
||
// TODO: 임시용이므로 이후에 제거 | ||
private ParticipantsResponse tempGetParticipantsResponseWithMemberFilter( | ||
Study study, Member member) { | ||
private ParticipantsResponse tempGetParticipantsResponseWithMemberFilter(Study study, Member member) { | ||
return participantRepository.findByStudyAndMember(study, member) | ||
.map(ParticipantResponse::from) | ||
.map(response -> ParticipantsResponse.from(List.of(response))) | ||
|
@@ -67,16 +61,14 @@ private ParticipantsResponse tempGetParticipantsResponseWithMemberFilter( | |
|
||
// TODO: 동적쿼리로 변경(memberId 유무에 따른 분기처리) | ||
@Transactional(readOnly = true) | ||
public ParticipantsResponse findParticipantsWithFilter( | ||
AuthMember authMember, Long studyId, @Nullable Long memberId | ||
) { | ||
public ParticipantsResponse findParticipantsWithFilter(AuthMember authMember, Long studyId, Long memberId) { | ||
Study study = studyRepository.findByIdIfExists(studyId); | ||
if (Objects.isNull(memberId)) { | ||
validateEverParticipated(authMember, study); | ||
return getParticipantsResponseWithoutMemberFilter(study); | ||
} | ||
Member member = memberRepository.findByIdIfExists(memberId); | ||
validateIsSameMemberId(authMember, memberId); | ||
Member member = memberRepository.findByIdIfExists(memberId); | ||
return getParticipantsResponseWithMemberFilter(study, member); | ||
} | ||
|
||
|
@@ -86,36 +78,32 @@ private void validateEverParticipated(AuthMember authMember, Study study) { | |
.orElseThrow(AuthorizationException::new); | ||
} | ||
|
||
private ParticipantsResponse getParticipantsResponseWithoutMemberFilter( | ||
Study study | ||
) { | ||
List<ParticipantResponse> responses = | ||
participantRepository.findByStudy(study) | ||
.stream() | ||
.map(ParticipantResponse::from) | ||
.toList(); | ||
private ParticipantsResponse getParticipantsResponseWithoutMemberFilter(Study study) { | ||
List<ParticipantResponse> responses = participantRepository.findByStudy(study) | ||
.stream() | ||
.map(ParticipantResponse::from) | ||
.toList(); | ||
return ParticipantsResponse.from(responses); | ||
} | ||
|
||
private ParticipantsResponse getParticipantsResponseWithMemberFilter( | ||
Study study, Member member | ||
) { | ||
ParticipantResponse response = | ||
participantRepository.findByStudyAndMember(study, member) | ||
.map(ParticipantResponse::from) | ||
.orElseThrow(ParticipantNotFoundException::new); | ||
private ParticipantsResponse getParticipantsResponseWithMemberFilter(Study study, Member member) { | ||
ParticipantResponse response = participantRepository.findByStudyAndMember(study, member) | ||
.map(ParticipantResponse::from) | ||
.orElseThrow(ParticipantNotFoundException::new); | ||
return ParticipantsResponse.from(List.of(response)); | ||
} | ||
|
||
public Long participateStudy(AuthMember authMember, Long studyId, ParticipateStudyRequest request) { | ||
Member member = memberRepository.findByIdIfExists(request.memberId()); | ||
validateIsSameMemberId(authMember, request.memberId()); | ||
Member member = memberRepository.findByIdIfExists(request.memberId()); | ||
Study study = studyRepository.findByIdIfExists(studyId); | ||
validateIsWaiting(study); | ||
|
||
study.validateIsWaiting(); | ||
Participant participant = Participant.createParticipantOfStudy(study, member, request.nickname()); | ||
participant.generateContents(study.getTotalCycle()); | ||
Participant saved = participantRepository.save(participant); | ||
return saved.getId(); | ||
participantRepository.save(participant); | ||
|
||
return participant.getId(); | ||
} | ||
|
||
private void validateIsSameMemberId(AuthMember authMember, Long memberId) { | ||
|
@@ -124,37 +112,14 @@ private void validateIsSameMemberId(AuthMember authMember, Long memberId) { | |
} | ||
} | ||
|
||
private void validateIsWaiting(Study study) { | ||
if (!study.isStep(Step.WAITING)) { | ||
throw new StudyAlreadyStartedException(); | ||
} | ||
} | ||
|
||
private void validateParticipantIsRelatedWith( | ||
Participant participant, AuthMember authMember, Study study | ||
) { | ||
validateMemberOwns(participant, authMember); | ||
validateParticipantIsIncludedIn(study, participant); | ||
} | ||
|
||
private void validateMemberOwns(Participant participant, AuthMember authMember) { | ||
Member member = memberRepository.findByIdIfExists(authMember.id()); | ||
if (participant.isNotCreatedBy(member)) { | ||
throw new AuthorizationException(); | ||
} | ||
} | ||
|
||
private void validateParticipantIsIncludedIn(Study study, Participant participant) { | ||
if (participant.isNotIncludedIn(study)) { | ||
throw new ParticipantNotBelongToStudyException(); | ||
} | ||
} | ||
|
||
public void deleteParticipant(AuthMember authMember, Long studyId, Long participantId) { | ||
Study study = studyRepository.findByIdIfExists(studyId); | ||
validateEverParticipated(authMember, study); | ||
Member member = memberRepository.findByIdIfExists(authMember.id()); | ||
Participant participant = participantRepository.findByIdIfExists(participantId); | ||
validateParticipantIsRelatedWith(participant, authMember, study); | ||
|
||
participant.validateIsCreatedByMember(member); | ||
participant.validateIsBelongsTo(study); | ||
|
||
participantRepository.delete(participant); | ||
} | ||
} |
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.
훨씬 좋네요 굳굳