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

상호 평가 반영 스케줄링 #602

Merged
merged 12 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ public Long create(final CreateReviewDto reviewDto) {
validateWriterCanReview(findAuction, writer);

final Review review = reviewDto.toEntity(findAuction, writer, target);
final Review persistReview = saveReviewAndUpdateReliability(review, target);

return persistReview.getId();
return reviewRepository.save(review)
.getId();
}

private void validateWriterCanReview(final Auction auction, final User writer) {
Expand All @@ -63,18 +63,9 @@ private void validateAlreadyReviewed(final Auction auction, final User writer) {
}
}

private Review saveReviewAndUpdateReliability(final Review review, final User target) {
final Review persistReview = reviewRepository.save(review);

final List<Review> targetReviews = reviewRepository.findAllByTargetId(target.getId());
target.updateReliability(targetReviews);

return persistReview;
}

public ReadReviewDetailDto readByReviewId(final Long reviewId) {
final Review findReview = reviewRepository.findById(reviewId)
.orElseThrow(() -> new ReviewNotFoundException("해당 평가를 찾을 수 없습니다."));
.orElseThrow(() -> new ReviewNotFoundException("해당 평가를 찾을 수 없습니다."));

return ReadReviewDetailDto.from(findReview);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.ddang.ddang.review.domain;

import com.ddang.ddang.user.domain.User;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

import java.util.List;
import java.util.Set;

import static java.util.stream.Collectors.toSet;

@RequiredArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
Copy link
Collaborator

Choose a reason for hiding this comment

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

질문 & 필수

해당 도메인은 Review의 일급 컬렉션으로 보입니다
다른 도메인 엔티티와는 다르게 영속화되지 않을 것이라고 보이는데
이 경우 @EqualsAndHashCode@ToString이 필요한지 모르겠네요

@ToString은 디버깅 시 도움이 될 수 있겠지만, @EqualsAndHashCode의 경우 저는 정말 필요없을 것 같습니다
이러한 일급 컬렉션의 동일성 비교를 할 일이 있을까 싶기도 하고, 동일성 비교를 하는 로직이 유효한 로직인지도 모르겠네요
지금은 동일성 비교를 하는 로직은 불필요할 것 같습니다

그래서 해당 질문과 이 애노테이션을 추가한 특별한 이유가 없다면 @EqualsAndHashCode는 삭제했으면 좋겠습니다
@ToString은 괜찮을 것 같기도 하고 이건 잘 모르겠군요

Copy link
Collaborator

Choose a reason for hiding this comment

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

칭찬

하지만 일급 컬렉션을 통해 관련 로직을 도메인 로직으로 분리하신 건 매우 개쩌는 것 같습니다
칭찬해요!!!!!!!!!!!!!!!!!!!!!!!!!@#!@#!@3

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

그냥 별 생각 없이 습관적으로 추가했던 것 같습니다. @EqualsAndHashCode는 삭제하도록 하겠습니다. @ToString은 원래 목적이 디버깅에 쓰려고 한 것이기 때문에 남겨두도록 하겠습니다.

public class Reviews {

private final List<Review> reviews;

public double addAllReviewScore() {
return reviews.stream()
.mapToDouble(review -> review.getScore().getValue())
.sum();
}

public int size() {
return reviews.size();
}

public boolean isEmpty() {
return reviews.isEmpty();
}

public Set<User> findReviewTargets() {
return reviews.stream()
.map(Review::getTarget)
.collect(toSet());
}

public List<Review> findReviewsByTarget(final User targetUser) {
return reviews.stream()
.filter(review -> review.getTarget().equals(targetUser))
.toList();
}

public Long findLastReviewId() {
final int lastIndex = reviews.size() - 1;

return reviews.get(lastIndex)
.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public interface JpaReviewRepository extends JpaRepository<Review, Long> {
List<Review> findAllByTargetId(final Long targetId);
Copy link
Collaborator

Choose a reason for hiding this comment

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

선택? 필수?

JOIN FETCH 부분은 개행을 일부러 안해주신 건가요?.?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

아무 생각 없었어요 ㅠ 개행 추가했습니다.


Optional<Review> findByAuctionIdAndWriterId(final Long auctionId, final Long writerId);

List<Review> findAllByIdGreaterThan(final Long id);
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,29 @@
package com.ddang.ddang.user.domain;

import com.ddang.ddang.review.domain.Review;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.List;

@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EqualsAndHashCode
@ToString
public class Reliability {

public static final Reliability INITIAL_RELIABILITY = new Reliability(null);
private static final double INITIAL_RELIABILITY_VALUE = Double.MIN_VALUE;
public static final Reliability INITIAL_RELIABILITY = new Reliability(INITIAL_RELIABILITY_VALUE);

private Double value;
private double value;
Copy link
Collaborator

Choose a reason for hiding this comment

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

칭찬

원시타입으로 바꿔주셔서 마음이 굉장히 편안해졌어요 감사합니다@@


public Reliability(final Double value) {
public Reliability(final double value) {
this.value = value;
}

public void updateReliability(final List<Review> reviews) {
if (reviews.isEmpty()) {
this.value = null;

return;
}

this.value = reviews.stream()
.mapToDouble(review -> review.getScore().getValue())
.average()
.orElseGet(null);
public double calculateReviewScoreSum(final int appliedReviewCount) {
return value * appliedReviewCount;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ddang.ddang.user.domain;

import com.ddang.ddang.common.entity.BaseCreateTimeEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Entity
@NoArgsConstructor
@Getter
@EqualsAndHashCode(of = "id", callSuper = false)
@ToString(of = {"id", })
Copy link
Collaborator

Choose a reason for hiding this comment

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

선택

이거 lastAppliedReviewId 까지 포함하려다가 안하신걸까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

앗 들켜버렸다

public class ReliabilityUpdateHistory extends BaseCreateTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private Long lastAppliedReviewId = 0L;

public ReliabilityUpdateHistory(final Long lastAppliedReviewId) {
this.lastAppliedReviewId = lastAppliedReviewId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.ddang.ddang.common.entity.BaseTimeEntity;
import com.ddang.ddang.image.domain.ProfileImage;
import com.ddang.ddang.review.domain.Review;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
Expand All @@ -23,8 +22,6 @@
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.List;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
Expand Down Expand Up @@ -89,7 +86,7 @@ public void withdrawal() {
this.deleted = DELETED_STATUS;
}

public void updateReliability(final List<Review> reviews) {
reliability.updateReliability(reviews);
public void updateReliability(final Reliability reliability) {
this.reliability = reliability;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.ddang.ddang.user.domain;

import com.ddang.ddang.review.domain.Reviews;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EqualsAndHashCode(of = "id", callSuper = false)
@ToString(of = {"id", "reliability", "appliedReviewCount"})
public class UserReliability {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
@JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "fk_user_reliability_user"), nullable = false)
private User user;

@Embedded
@AttributeOverride(name = "value", column = @Column(name = "reliability"))
private Reliability reliability;

private int appliedReviewCount = 0;

public UserReliability(final User user) {
this.user = user;
this.reliability = user.getReliability();
}

public void updateReliability(final Reviews newReviews) {
if (newReviews.isEmpty()) {
return;
}
final Reliability newReliability = calculateNewReliability(newReviews);

this.reliability = newReliability;
addAppliedReviewCount(newReviews.size());
user.updateReliability(newReliability);
}

private Reliability calculateNewReliability(final Reviews newReviews) {
final double currentReviewScoreSum = reliability.calculateReviewScoreSum(appliedReviewCount);
final double newReviewScoreSum = newReviews.addAllReviewScore();
final int allReviewCount = appliedReviewCount + newReviews.size();

final double newReliabilityValue = (currentReviewScoreSum + newReviewScoreSum) / allReviewCount;

return new Reliability(newReliabilityValue);
}

private void addAppliedReviewCount(final int newReviewCount) {
this.appliedReviewCount += newReviewCount;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.ddang.ddang.user.infrastructure.persistence;

import com.ddang.ddang.user.domain.ReliabilityUpdateHistory;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface JpaReliabilityUpdateHistoryRepository extends JpaRepository<ReliabilityUpdateHistory, Long> {

Optional<ReliabilityUpdateHistory> findFirstByOrderByIdDesc();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.ddang.ddang.user.infrastructure.persistence;

import com.ddang.ddang.user.domain.UserReliability;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface JpaUserReliabilityRepository extends JpaRepository<UserReliability, Long> {

Optional<UserReliability> findByUserId(final Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;

@IsolateDatabase
Expand All @@ -28,15 +29,12 @@ class ReviewServiceTest extends ReviewServiceFixture {
ReviewService reviewService;

@Test
void 평가를_등록한고_평가_상대의_신뢰도를_갱신한다() {
void 평가를_등록한다() {
// when
final Long actual = reviewService.create(구매자에_대한_평가_등록을_위한_DTO);

// then
SoftAssertions.assertSoftly(softAssertions -> {
softAssertions.assertThat(actual).isPositive();
softAssertions.assertThat(구매자.getReliability().getValue()).isEqualTo(구매자가_새로운_평가_점수를_받고난_후의_신뢰도_점수);
});
assertThat(actual).isPositive();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public class ReviewServiceFixture {
@Autowired
private JpaReviewRepository reviewRepository;

private Double 구매자가_판매자1에게_받은_평가_점수 = 5.0d;
private Double 구매자가_판매자2에게_받은_평가_점수 = 1.0d;
private Double 구매자가_받을_새로운_평가_점수 = 4.5d;
private double 구매자가_판매자1에게_받은_평가_점수 = 5.0d;
private double 구매자가_판매자2에게_받은_평가_점수 = 1.0d;
private double 구매자가_받을_새로운_평가_점수 = 4.5d;

protected Double 구매자가_새로운_평가_점수를_받고난_후의_신뢰도_점수 =
protected double 구매자가_새로운_평가_점수를_받고난_후의_신뢰도_점수 =
(구매자가_판매자1에게_받은_평가_점수 + 구매자가_판매자2에게_받은_평가_점수 + 구매자가_받을_새로운_평가_점수) / 3;
protected Long 존재하지_않는_사용자 = -999L;
protected User 판매자1;
Expand Down
Loading