Skip to content

Commit 50c6843

Browse files
step1 - 레거시 코드 리팩토링 리뷰요청 드립니다. (#812)
* feat: Answers 일급 컬렉션 적용 * feat: Question - validateOwner() * feat: Question delete() & validateOwner TestCode * refactor: Question 캡슐화 * refactor: 구조 개선 * refactor: Answer 클래스 수정(delete 메소드 역할 분리) * refactor: Answers 클래스 개선(테스트코드 AnswerTest로 확인 가능) * test: Answer test 추가 * refactor: Question 클래스 수정 * refactor: Question 클래스 객체 분리 * refactor: 공통 Delete 전용 BaseEntity 생성 * refactor: Answer 클래스에도 공통 delete BaseEntity 적용 * style: 불필요 로직 삭제 * refactor: DeleteHistory 정적 팩토리 메소드 추가 - 적용
1 parent de587b9 commit 50c6843

File tree

10 files changed

+197
-101
lines changed

10 files changed

+197
-101
lines changed
Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,19 @@
11
package nextstep.qna.domain;
22

3+
import nextstep.qna.CannotDeleteException;
34
import nextstep.qna.NotFoundException;
45
import nextstep.qna.UnAuthorizedException;
56
import nextstep.users.domain.NsUser;
67

78
import java.time.LocalDateTime;
89

9-
public class Answer {
10-
private Long id;
11-
10+
public class Answer extends DeletableBaseEntity {
1211
private NsUser writer;
1312

1413
private Question question;
1514

1615
private String contents;
1716

18-
private boolean deleted = false;
19-
20-
private LocalDateTime createdDate = LocalDateTime.now();
21-
22-
private LocalDateTime updatedDate;
23-
2417
public Answer() {
2518
}
2619

@@ -29,12 +22,12 @@ public Answer(NsUser writer, Question question, String contents) {
2922
}
3023

3124
public Answer(Long id, NsUser writer, Question question, String contents) {
32-
this.id = id;
33-
if(writer == null) {
25+
super(id);
26+
if (writer == null) {
3427
throw new UnAuthorizedException();
3528
}
3629

37-
if(question == null) {
30+
if (question == null) {
3831
throw new NotFoundException();
3932
}
4033

@@ -43,19 +36,6 @@ public Answer(Long id, NsUser writer, Question question, String contents) {
4336
this.contents = contents;
4437
}
4538

46-
public Long getId() {
47-
return id;
48-
}
49-
50-
public Answer setDeleted(boolean deleted) {
51-
this.deleted = deleted;
52-
return this;
53-
}
54-
55-
public boolean isDeleted() {
56-
return deleted;
57-
}
58-
5939
public boolean isOwner(NsUser writer) {
6040
return this.writer.equals(writer);
6141
}
@@ -64,10 +44,6 @@ public NsUser getWriter() {
6444
return writer;
6545
}
6646

67-
public String getContents() {
68-
return contents;
69-
}
70-
7147
public void toQuestion(Question question) {
7248
this.question = question;
7349
}
@@ -76,4 +52,19 @@ public void toQuestion(Question question) {
7652
public String toString() {
7753
return "Answer [id=" + getId() + ", writer=" + writer + ", contents=" + contents + "]";
7854
}
55+
56+
public void delete(NsUser loginUser) throws CannotDeleteException {
57+
validateDeletableUser(loginUser);
58+
delete();
59+
}
60+
61+
private void validateDeletableUser(NsUser loginUser) throws CannotDeleteException {
62+
if (!isOwner(loginUser)) {
63+
throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다.");
64+
}
65+
}
66+
67+
public DeleteHistory deleteHistory() {
68+
return DeleteHistory.from(ContentType.ANSWER, getId(), getWriter(), LocalDateTime.now());
69+
}
7970
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package nextstep.qna.domain;
2+
3+
import nextstep.qna.CannotDeleteException;
4+
import nextstep.users.domain.NsUser;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
public class Answers {
10+
11+
private List<Answer> answers;
12+
13+
public Answers() {
14+
this(new ArrayList<>());
15+
}
16+
17+
public Answers(List<Answer> answers) {
18+
this.answers = new ArrayList<>(answers);
19+
}
20+
21+
public void add(Answer answer) {
22+
answers.add(answer);
23+
}
24+
25+
public void deleteAll(NsUser loginUser) throws CannotDeleteException {
26+
for (Answer answer : answers) {
27+
answer.delete(loginUser);
28+
}
29+
}
30+
31+
public List<DeleteHistory> toDeleteHistories() {
32+
List<DeleteHistory> deleteHistories = new ArrayList<>();
33+
for (Answer answer : answers) {
34+
deleteHistories.add(answer.deleteHistory());
35+
}
36+
return deleteHistories;
37+
}
38+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package nextstep.qna.domain;
2+
3+
import java.time.LocalDateTime;
4+
5+
public abstract class DeletableBaseEntity {
6+
7+
private Long id;
8+
private boolean deleted = false;
9+
10+
private LocalDateTime createdDate = LocalDateTime.now();
11+
12+
private LocalDateTime updatedDate;
13+
14+
protected DeletableBaseEntity() {
15+
}
16+
17+
public DeletableBaseEntity(Long id) {
18+
this.id = id;
19+
}
20+
21+
public Long getId() {
22+
return id;
23+
}
24+
25+
protected void delete() {
26+
this.deleted = true;
27+
}
28+
29+
public boolean isDeleted() {
30+
return deleted;
31+
}
32+
}

src/main/java/nextstep/qna/domain/DeleteHistory.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ public class DeleteHistory {
1919
public DeleteHistory() {
2020
}
2121

22-
public DeleteHistory(ContentType contentType, Long contentId, NsUser deletedBy, LocalDateTime createdDate) {
22+
private DeleteHistory(ContentType contentType, Long contentId, NsUser deletedBy, LocalDateTime createdDate) {
2323
this.contentType = contentType;
2424
this.contentId = contentId;
2525
this.deletedBy = deletedBy;
2626
this.createdDate = createdDate;
2727
}
2828

29+
public static DeleteHistory from(ContentType contentType, Long contentId, NsUser deletedBy, LocalDateTime createdDate) {
30+
return new DeleteHistory(contentType, contentId, deletedBy, LocalDateTime.now());
31+
}
32+
2933
@Override
3034
public boolean equals(Object o) {
3135
if (this == o) return true;
Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,27 @@
11
package nextstep.qna.domain;
22

3+
import nextstep.qna.CannotDeleteException;
34
import nextstep.users.domain.NsUser;
45

56
import java.time.LocalDateTime;
67
import java.util.ArrayList;
78
import java.util.List;
89

9-
public class Question {
10-
private Long id;
11-
12-
private String title;
13-
14-
private String contents;
10+
public class Question extends DeletableBaseEntity {
11+
private QuestionContent content;
1512

1613
private NsUser writer;
1714

18-
private List<Answer> answers = new ArrayList<>();
19-
20-
private boolean deleted = false;
21-
22-
private LocalDateTime createdDate = LocalDateTime.now();
23-
24-
private LocalDateTime updatedDate;
25-
26-
public Question() {
27-
}
15+
private Answers answers = new Answers();
2816

2917
public Question(NsUser writer, String title, String contents) {
3018
this(0L, writer, title, contents);
3119
}
3220

3321
public Question(Long id, NsUser writer, String title, String contents) {
34-
this.id = id;
22+
super(id);
3523
this.writer = writer;
36-
this.title = title;
37-
this.contents = contents;
38-
}
39-
40-
public Long getId() {
41-
return id;
42-
}
43-
44-
public String getTitle() {
45-
return title;
46-
}
47-
48-
public Question setTitle(String title) {
49-
this.title = title;
50-
return this;
51-
}
52-
53-
public String getContents() {
54-
return contents;
55-
}
56-
57-
public Question setContents(String contents) {
58-
this.contents = contents;
59-
return this;
24+
this.content = new QuestionContent(title, contents);
6025
}
6126

6227
public NsUser getWriter() {
@@ -72,21 +37,27 @@ public boolean isOwner(NsUser loginUser) {
7237
return writer.equals(loginUser);
7338
}
7439

75-
public Question setDeleted(boolean deleted) {
76-
this.deleted = deleted;
77-
return this;
40+
private void validateOwner(NsUser loginUser) throws CannotDeleteException {
41+
if (!isOwner(loginUser)) {
42+
throw new CannotDeleteException("질문을 삭제할 권한이 없습니다.");
43+
}
7844
}
7945

80-
public boolean isDeleted() {
81-
return deleted;
46+
public DeleteHistory deleteHistory() {
47+
return DeleteHistory.from(ContentType.QUESTION, getId(), writer, LocalDateTime.now());
8248
}
8349

84-
public List<Answer> getAnswers() {
85-
return answers;
50+
public void delete(NsUser loginUser) throws CannotDeleteException {
51+
validateOwner(loginUser);
52+
delete();
53+
54+
answers.deleteAll(loginUser);
8655
}
8756

88-
@Override
89-
public String toString() {
90-
return "Question [id=" + getId() + ", title=" + title + ", contents=" + contents + ", writer=" + writer + "]";
57+
public List<DeleteHistory> toDeleteHistories() {
58+
List<DeleteHistory> deleteHistories = new ArrayList<>();
59+
deleteHistories.add(deleteHistory());
60+
deleteHistories.addAll(answers.toDeleteHistories());
61+
return deleteHistories;
9162
}
9263
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package nextstep.qna.domain;
2+
3+
public class QuestionContent {
4+
private String title;
5+
private String contents;
6+
7+
public QuestionContent(String title, String contents) {
8+
this.title = title;
9+
this.contents = contents;
10+
}
11+
}

src/main/java/nextstep/qna/service/QnAService.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import org.springframework.transaction.annotation.Transactional;
99

1010
import javax.annotation.Resource;
11-
import java.time.LocalDateTime;
1211
import java.util.ArrayList;
1312
import java.util.List;
1413

@@ -26,24 +25,9 @@ public class QnAService {
2625
@Transactional
2726
public void deleteQuestion(NsUser loginUser, long questionId) throws CannotDeleteException {
2827
Question question = questionRepository.findById(questionId).orElseThrow(NotFoundException::new);
29-
if (!question.isOwner(loginUser)) {
30-
throw new CannotDeleteException("질문을 삭제할 권한이 없습니다.");
31-
}
28+
question.delete(loginUser);
3229

33-
List<Answer> answers = question.getAnswers();
34-
for (Answer answer : answers) {
35-
if (!answer.isOwner(loginUser)) {
36-
throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다.");
37-
}
38-
}
39-
40-
List<DeleteHistory> deleteHistories = new ArrayList<>();
41-
question.setDeleted(true);
42-
deleteHistories.add(new DeleteHistory(ContentType.QUESTION, questionId, question.getWriter(), LocalDateTime.now()));
43-
for (Answer answer : answers) {
44-
answer.setDeleted(true);
45-
deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now()));
46-
}
30+
List<DeleteHistory> deleteHistories = question.toDeleteHistories();
4731
deleteHistoryService.saveAll(deleteHistories);
4832
}
4933
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,43 @@
11
package nextstep.qna.domain;
22

3+
import nextstep.qna.CannotDeleteException;
4+
import nextstep.users.domain.NsUser;
35
import nextstep.users.domain.NsUserTest;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.time.LocalDateTime;
9+
10+
import static org.assertj.core.api.Assertions.assertThat;
11+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
412

513
public class AnswerTest {
614
public static final Answer A1 = new Answer(NsUserTest.JAVAJIGI, QuestionTest.Q1, "Answers Contents1");
715
public static final Answer A2 = new Answer(NsUserTest.SANJIGI, QuestionTest.Q1, "Answers Contents2");
16+
17+
@Test
18+
void delete_다른사람이_쓴_답변이_있으면_삭제불가() {
19+
NsUser user = NsUserTest.JAVAJIGI;
20+
Answer answer = AnswerTest.A2;
21+
assertThatThrownBy(() -> answer.delete(user))
22+
.isInstanceOf(CannotDeleteException.class);
23+
}
24+
25+
@Test
26+
void delete_성공() throws CannotDeleteException {
27+
NsUser user = NsUserTest.JAVAJIGI;
28+
Answer answer = AnswerTest.A1;
29+
30+
answer.delete(user);
31+
32+
assertThat(answer.isDeleted()).isTrue();
33+
}
34+
35+
@Test
36+
void deleteHistory_생성() {
37+
Answer answer = AnswerTest.A1;
38+
39+
DeleteHistory history = answer.deleteHistory();
40+
41+
assertThat(history).isEqualTo(DeleteHistory.from(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now()));
42+
}
843
}

0 commit comments

Comments
 (0)