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

[BE] refactor: 도메인을 활용한 하이라이트 추가 및 수정 로직 리팩토링 #859

Merged
merged 29 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d7bcdb1
refactor: 인덱스 범위 도메인명 변경 및 lineIndex 책임을 Highlight로 이동
skylar1220 Oct 15, 2024
d689cd6
refactor: 하이라이트 한줄 도메인 추가
skylar1220 Oct 15, 2024
588c2ee
refactor: 한 답변에 표시된 하이라이트 여러줄 도메인 추가
skylar1220 Oct 15, 2024
8046c1a
refactor: dto 필드의 속성을 가져오는 메서드 추가
skylar1220 Oct 15, 2024
131304e
feat: 답변 id에 해당하는 하이라이트를 삭제하는 메서드 추가
skylar1220 Oct 15, 2024
bf64ea9
refactor: 중복되는 검증 및 로직 제거
skylar1220 Oct 15, 2024
d68451e
refactor: 생성자 추가
skylar1220 Oct 15, 2024
7e84d45
refactor: 하이라이트 객체 매핑을 위한 mapper 분리
skylar1220 Oct 15, 2024
0efcc43
refactor: 하이라이트 서비스에 mapper 적용 및 삭제 로직 단순화
skylar1220 Oct 15, 2024
7557ce9
refactor: 사용하지 않는 클래스 및 메서드 삭제
skylar1220 Oct 15, 2024
a807959
refactor: 도메인과 엔티티 패키지 분리
skylar1220 Oct 15, 2024
206f712
refactor: dto 메서드로 대체
skylar1220 Oct 15, 2024
1df8f12
refactor: 하이라이트 라인 관련 예외 추상화
skylar1220 Oct 15, 2024
65dd10e
refactor: 하이라이트 라인 도메인명 수정
skylar1220 Oct 15, 2024
1e053d8
refactor: 필드명 수정
skylar1220 Oct 15, 2024
6c98099
refactor: 변수명 및 메서드명 수정
skylar1220 Oct 15, 2024
30c9518
refactor: 필드명 수정 및 공백 제거
skylar1220 Oct 15, 2024
52f9e1a
refactor: 생성자 체이닝
skylar1220 Oct 15, 2024
4a515c8
refactor: 중복 제거 방식 및 반환 타입 변경
skylar1220 Oct 15, 2024
a243d24
refactor: 도메인에서 필요하지 않은 필드인 lineIndex 삭제 및 생성자 수정
skylar1220 Oct 15, 2024
e060289
refactor: 세션을 통해 리뷰 그룹 가져오기 적용
skylar1220 Oct 15, 2024
26428e3
refactor: 메서드 분리
skylar1220 Oct 15, 2024
9eac3bc
refactor: 사용하지 않는 생성자 제거
skylar1220 Oct 15, 2024
b757b0d
refactor: 도메인명 변경
skylar1220 Oct 15, 2024
51654c4
refactor: 엔티티 패키지 삭제 및 도메인 패키지로 통
skylar1220 Oct 15, 2024
e49734b
refactor: 빈 하이라이트 요청이 왔을 때 아무것도 저장하지 않는 것 검증하는 테스트 추가
skylar1220 Oct 15, 2024
d9a2228
refactor: 변수명 수정 및 메서드 정렬, 개행
skylar1220 Oct 15, 2024
7dcc5e2
refactor: 접근 제어자 추가 및 static import 제거
skylar1220 Oct 15, 2024
80479d5
refactor: 사용하지 않는 메서드 삭제
skylar1220 Oct 15, 2024
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 @@ -22,7 +22,7 @@ public ResponseEntity<Void> highlight(
@Valid @RequestBody HighlightsRequest request,
@ReviewGroupSession ReviewGroup reviewGroup
) {
highlightService.highlight(request, reviewGroup);
highlightService.editHighlight(request, reviewGroup);
return ResponseEntity.ok().build();
}
}
10 changes: 7 additions & 3 deletions backend/src/main/java/reviewme/highlight/domain/Highlight.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ public class Highlight {
@Column(name = "answer_id", nullable = false)
private long answerId;

@Column(name = "line_index", nullable = false)
private int lineIndex;

@Embedded
private HighlightPosition highlightPosition;
private HighlightRange highlightRange;

public Highlight(long answerId, int lineIndex, int startIndex, int endIndex) {
public Highlight(long answerId, int lineIndex, HighlightRange range) {
Copy link
Contributor

Choose a reason for hiding this comment

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

생성자 추가했으니 기존 생성자를 체이닝하면 어떨까요? 개인적으로는 지금 이 생성자가 주 생성자가 되었으면 하는 바람입니다~

Copy link
Contributor Author

@skylar1220 skylar1220 Oct 15, 2024

Choose a reason for hiding this comment

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

생성자 체이닝을 놓쳤네요 반완!

this.answerId = answerId;
this.highlightPosition = new HighlightPosition(lineIndex, startIndex, endIndex);
this.lineIndex = lineIndex;
this.highlightRange = range;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,36 @@
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import reviewme.highlight.domain.exception.HighlightStartIndexExceedEndIndexException;
import reviewme.highlight.domain.exception.NegativeHighlightIndexException;
import reviewme.highlight.domain.exception.InvalidHighlightIndexRangeException;

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

@Column(name = "line_index", nullable = false)
private int lineIndex;
public class HighlightRange {

@Column(name = "start_index", nullable = false)
private int startIndex;

@Column(name = "end_index", nullable = false)
private int endIndex;

public HighlightPosition(int lineIndex, int startIndex, int endIndex) {
public HighlightRange(int startIndex, int endIndex) {
validateNonNegativeIndexNumber(startIndex, endIndex);
validateEndIndexOverStartIndex(startIndex, endIndex);
this.lineIndex = lineIndex;
this.startIndex = startIndex;
this.endIndex = endIndex;
}

private void validateNonNegativeIndexNumber(long startIndex, long endIndex) {
private void validateNonNegativeIndexNumber(int startIndex, int endIndex) {
if (startIndex < 0 || endIndex < 0) {
throw new NegativeHighlightIndexException(startIndex, endIndex);
throw new InvalidHighlightIndexRangeException(startIndex, endIndex);
}
}

private void validateEndIndexOverStartIndex(long startIndex, long endIndex) {
private void validateEndIndexOverStartIndex(int startIndex, int endIndex) {
if (startIndex > endIndex) {
throw new HighlightStartIndexExceedEndIndexException(startIndex, endIndex);
throw new InvalidHighlightIndexRangeException(startIndex, endIndex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package reviewme.highlight.domain;

import java.util.HashSet;
import java.util.Set;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import reviewme.highlight.domain.exception.HighlightIndexExceedLineLengthException;

@Getter
@EqualsAndHashCode
public class HighlightedLine {

private final String content;
private final Set<HighlightRange> ranges;

public HighlightedLine(String content) {
this.content = content;
this.ranges = new HashSet<>();
}

public void addRange(int startIndex, int endIndex) {
validateRangeByContentLength(startIndex, endIndex);
ranges.add(new HighlightRange(startIndex, endIndex));
}

private void validateRangeByContentLength(int startIndex, int endIndex) {
int contentLength = content.length();
if (startIndex >= contentLength || endIndex >= contentLength) {
throw new HighlightIndexExceedLineLengthException(content.length(), startIndex, endIndex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package reviewme.highlight.domain;

import java.util.Arrays;
import java.util.List;
import lombok.Getter;
import reviewme.highlight.domain.exception.InvalidHighlightLineIndexException;
import reviewme.highlight.domain.exception.NegativeHighlightLineIndexException;

@Getter
public class HighlightedLines {

public static final String LINE_SEPARATOR = "\n";

private final List<HighlightedLine> lines;

public HighlightedLines(String content) {
this.lines = Arrays.stream(content.split(LINE_SEPARATOR))
.map(HighlightedLine::new)
.toList();
}

public void addRange(int lineIndex, int startIndex, int endIndex) {
validateNonNegativeLineIndexNumber(lineIndex);
validateLineIndexRange(lineIndex);
HighlightedLine line = lines.get(lineIndex);
line.addRange(startIndex, endIndex);
}

private void validateNonNegativeLineIndexNumber(int lineIndex) {
if (lineIndex < 0) {
throw new NegativeHighlightLineIndexException(lineIndex);
}
}

private void validateLineIndexRange(int lineIndex) {
if (lineIndex >= lines.size()) {
throw new InvalidHighlightLineIndexException(lineIndex, lines.size());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package reviewme.highlight.domain.exception;

import lombok.extern.slf4j.Slf4j;
import reviewme.global.exception.BadRequestException;

@Slf4j
public class HighlightIndexExceedLineLengthException extends BadRequestException {

public HighlightIndexExceedLineLengthException(int lineLength, int startIndex, int endIndex) {
super("하이라이트 위치가 텍스트의 범위를 벗어났어요.");
log.info("Highlight index exceed line length - lineLength: {}, startIndex: {}, endIndex: {}",
lineLength, startIndex, endIndex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@Slf4j
public class HighlightStartIndexExceedEndIndexException extends BadRequestException {

public HighlightStartIndexExceedEndIndexException(long startIndex, long endIndex) {
public HighlightStartIndexExceedEndIndexException(int startIndex, int endIndex) {
super("하이라이트 끝 위치는 시작 위치보다 같거나 커야 해요.");
log.info("Highlight start index exceed end index - startIndex: {}, endIndex: {}", startIndex, endIndex);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package reviewme.highlight.domain.exception;

import lombok.extern.slf4j.Slf4j;
import reviewme.global.exception.BadRequestException;

@Slf4j
public class InvalidHighlightIndexRangeException extends BadRequestException {

public InvalidHighlightIndexRangeException(int startIndex, int endIndex) {
super("유효하지 않은 하이라이트 위치에요. 하이라이트 시작 위치: %d, 종료 위치: %d".formatted(startIndex, endIndex));
log.info("Highlight index is a negative number - startIndex: {}, endIndex: {}", startIndex, endIndex);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package reviewme.highlight.service.exception;
package reviewme.highlight.domain.exception;

import lombok.extern.slf4j.Slf4j;
import reviewme.global.exception.BadRequestException;

@Slf4j
public class InvalidHighlightLineIndexException extends BadRequestException {

public InvalidHighlightLineIndexException(long submittedLineIndex, long providedMaxLineIndex) {
super("줄 번호는 %d 이하여야해요.".formatted(providedMaxLineIndex));
public InvalidHighlightLineIndexException(int submittedLineIndex, int providedMaxLineIndex) {
super("하이라이트 위치가 답변의 라인을 벗어났어요.");
log.info("Line index is out of bound - maxIndex: {}, submittedLineIndex: {}", providedMaxLineIndex,
submittedLineIndex);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package reviewme.highlight.domain.exception;

import lombok.extern.slf4j.Slf4j;
import reviewme.global.exception.BadRequestException;

@Slf4j
public class NegativeHighlightLineIndexException extends BadRequestException {

public NegativeHighlightLineIndexException(int lineIndex) {
super("하이라이트 할 라인의 위치는 0 이상의 수이어야 해요.");
log.info("Highlight index is a negative number - lineIndex: {}", lineIndex);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package reviewme.highlight.repository;

import java.util.Collection;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import reviewme.highlight.domain.Highlight;

public interface HighlightRepository extends JpaRepository<Highlight, Long> {

@Modifying
@Query("""
DELETE FROM Highlight h
WHERE h.answerId IN :answerIds
""")
void deleteAllByAnswerIds(Collection<Long> answerIds);
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package reviewme.highlight.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reviewme.highlight.domain.Highlight;
import reviewme.highlight.repository.HighlightRepository;
import reviewme.highlight.service.dto.HighlightIndexRangeRequest;
import reviewme.highlight.service.dto.HighlightRequest;
import reviewme.highlight.service.dto.HighlightedLineRequest;
import reviewme.highlight.service.dto.HighlightsRequest;
import reviewme.highlight.service.mapper.HighlightMapper;
import reviewme.highlight.service.validator.HighlightValidator;
import reviewme.review.domain.Answer;
import reviewme.review.repository.AnswerRepository;
import reviewme.reviewgroup.domain.ReviewGroup;

Expand All @@ -25,36 +21,16 @@ public class HighlightService {
private final AnswerRepository answerRepository;

private final HighlightValidator highlightValidator;
private final HighlightMapper highlightMapper;

@Transactional
public void highlight(HighlightsRequest request, ReviewGroup reviewGroup) {
long reviewGroupId = reviewGroup.getId();
highlightValidator.validate(request, reviewGroupId);
deleteOldHighlight(request.questionId(), reviewGroupId);
saveNewHighlight(request);
}

private void deleteOldHighlight(long questionId, long reviewGroupId) {
Set<Answer> answersByReviewGroup = answerRepository.findAllByReviewGroupId(reviewGroupId);
List<Long> answersByReviewQuestion = answersByReviewGroup.stream()
.filter(answer -> answer.getQuestionId() == questionId)
.map(Answer::getId)
.toList();
public void editHighlight(HighlightsRequest highlightsRequest, ReviewGroup reviewGroup) {
highlightValidator.validate(highlightsRequest, reviewGroup);
List<Highlight> highlights = highlightMapper.mapToHighlights(highlightsRequest);

highlightRepository.deleteAllById(answersByReviewQuestion);
}
Set<Long> answerIds = answerRepository.findIdsByQuestionId(highlightsRequest.questionId());
highlightRepository.deleteAllByAnswerIds(answerIds);

private void saveNewHighlight(HighlightsRequest highlightsRequest) {
List<Highlight> highlights = new ArrayList<>();
for (HighlightRequest highlight : highlightsRequest.highlights()) {
for (HighlightedLineRequest line : highlight.lines()) {
for (HighlightIndexRangeRequest range : line.ranges()) {
Highlight highLight = new Highlight(highlight.answerId(),
line.index(), range.startIndex(), range.endIndex());
highlights.add(highLight);
}
}
}
highlightRepository.saveAll(highlights);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ public record HighlightsRequest(
@Valid @NotNull(message = "하이라이트할 부분을 입력해주세요.")
List<HighlightRequest> highlights
) {

public List<Long> getUniqueAnswerIds() {
return highlights()
.stream()
.map(HighlightRequest::answerId)
.distinct()
.toList();
}
}

This file was deleted.

Loading