From 263e54279aac14ceb8929778b988764027f2930b Mon Sep 17 00:00:00 2001 From: ho-jun97 Date: Mon, 8 Dec 2025 22:31:17 +0900 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20quest=EC=97=90=20delete=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=B3=B4=EB=82=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/qna/domain/Question.java | 30 +++++++++++++++++++ .../java/nextstep/qna/service/QnAService.java | 24 ++------------- .../nextstep/qna/domain/QuestionTest.java | 21 +++++++++++++ 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/main/java/nextstep/qna/domain/Question.java b/src/main/java/nextstep/qna/domain/Question.java index b623c52c76..7475333805 100644 --- a/src/main/java/nextstep/qna/domain/Question.java +++ b/src/main/java/nextstep/qna/domain/Question.java @@ -1,5 +1,6 @@ package nextstep.qna.domain; +import nextstep.qna.CannotDeleteException; import nextstep.users.domain.NsUser; import java.time.LocalDateTime; @@ -85,6 +86,35 @@ public List getAnswers() { return answers; } + public List delete(NsUser loginUser) throws CannotDeleteException { + validateDeletableBy(loginUser); + + List deleteHistories = new ArrayList<>(); + + this.setDeleted(true); + + deleteHistories.add(new DeleteHistory(ContentType.QUESTION, this.id, this.getWriter(), LocalDateTime.now())); + + for (Answer answer : answers) { + answer.setDeleted(true); + deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now())); + } + + return deleteHistories; + } + + public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { + if (!isOwner(loginUser)) { + throw new CannotDeleteException("질문을 삭제할 권한이 없습니다."); + } + + for (Answer answer : answers) { + if (!answer.isOwner(loginUser)) { + throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); + } + } + } + @Override public String toString() { return "Question [id=" + getId() + ", title=" + title + ", contents=" + contents + ", writer=" + writer + "]"; diff --git a/src/main/java/nextstep/qna/service/QnAService.java b/src/main/java/nextstep/qna/service/QnAService.java index 5741c84d65..5d8787aef4 100644 --- a/src/main/java/nextstep/qna/service/QnAService.java +++ b/src/main/java/nextstep/qna/service/QnAService.java @@ -8,9 +8,6 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; @Service("qnaService") public class QnAService { @@ -26,24 +23,7 @@ public class QnAService { @Transactional public void deleteQuestion(NsUser loginUser, long questionId) throws CannotDeleteException { Question question = questionRepository.findById(questionId).orElseThrow(NotFoundException::new); - if (!question.isOwner(loginUser)) { - throw new CannotDeleteException("질문을 삭제할 권한이 없습니다."); - } - List answers = question.getAnswers(); - for (Answer answer : answers) { - if (!answer.isOwner(loginUser)) { - throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); - } - } - - List deleteHistories = new ArrayList<>(); - question.setDeleted(true); - deleteHistories.add(new DeleteHistory(ContentType.QUESTION, questionId, question.getWriter(), LocalDateTime.now())); - for (Answer answer : answers) { - answer.setDeleted(true); - deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now())); - } - deleteHistoryService.saveAll(deleteHistories); + deleteHistoryService.saveAll(question.delete(loginUser)); } -} +} \ No newline at end of file diff --git a/src/test/java/nextstep/qna/domain/QuestionTest.java b/src/test/java/nextstep/qna/domain/QuestionTest.java index 3b87823963..82955165eb 100644 --- a/src/test/java/nextstep/qna/domain/QuestionTest.java +++ b/src/test/java/nextstep/qna/domain/QuestionTest.java @@ -1,8 +1,29 @@ package nextstep.qna.domain; +import nextstep.qna.CannotDeleteException; import nextstep.users.domain.NsUserTest; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; public class QuestionTest { public static final Question Q1 = new Question(NsUserTest.JAVAJIGI, "title1", "contents1"); public static final Question Q2 = new Question(NsUserTest.SANJIGI, "title2", "contents2"); + + @Test + void 삭제할_수_없는_유저일_때() { + assertThatThrownBy(()-> + Q1.validateDeletableBy(NsUserTest.SANJIGI) + ).isInstanceOf(CannotDeleteException.class) + .hasMessageContaining("질문을 삭제할 권한이 없습니다."); + + } + + @Test + void 질문_삭제_성공() throws CannotDeleteException { + Q1.delete(NsUserTest.JAVAJIGI); + + assertThat(Q1.isDeleted()).isTrue(); + } } From b414d7fa3a57d64ef03c0502e6043c6d969af3bb Mon Sep 17 00:00:00 2001 From: ho-jun97 Date: Mon, 8 Dec 2025 23:21:49 +0900 Subject: [PATCH 2/6] =?UTF-8?q?refactor:=20answer=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20answers=20=EC=97=90=20=ED=8F=AC=EC=9E=A5?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20(=EC=9D=BC=EA=B8=89=20=EC=BB=AC=EB=A0=89?= =?UTF-8?q?=EC=85=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/qna/domain/Answer.java | 13 ++++- .../java/nextstep/qna/domain/Answers.java | 50 +++++++++++++++++++ .../java/nextstep/qna/domain/Question.java | 17 +++---- .../java/nextstep/qna/domain/AnswerTest.java | 12 +++++ .../java/nextstep/qna/domain/AnswersTest.java | 14 ++++++ .../nextstep/qna/domain/QuestionTest.java | 1 - 6 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 src/main/java/nextstep/qna/domain/Answers.java create mode 100644 src/test/java/nextstep/qna/domain/AnswersTest.java diff --git a/src/main/java/nextstep/qna/domain/Answer.java b/src/main/java/nextstep/qna/domain/Answer.java index cf681811e7..daa1ab3a9b 100644 --- a/src/main/java/nextstep/qna/domain/Answer.java +++ b/src/main/java/nextstep/qna/domain/Answer.java @@ -1,5 +1,6 @@ package nextstep.qna.domain; +import nextstep.qna.CannotDeleteException; import nextstep.qna.NotFoundException; import nextstep.qna.UnAuthorizedException; import nextstep.users.domain.NsUser; @@ -47,11 +48,15 @@ public Long getId() { return id; } - public Answer setDeleted(boolean deleted) { + private Answer setDeleted(boolean deleted) { this.deleted = deleted; return this; } + public void delete() { + setDeleted(true); + } + public boolean isDeleted() { return deleted; } @@ -72,6 +77,12 @@ public void toQuestion(Question question) { this.question = question; } + public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { + if (!isOwner(loginUser)) { + throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); + } + } + @Override public String toString() { return "Answer [id=" + getId() + ", writer=" + writer + ", contents=" + contents + "]"; diff --git a/src/main/java/nextstep/qna/domain/Answers.java b/src/main/java/nextstep/qna/domain/Answers.java new file mode 100644 index 0000000000..c6c8cd07c2 --- /dev/null +++ b/src/main/java/nextstep/qna/domain/Answers.java @@ -0,0 +1,50 @@ +package nextstep.qna.domain; + +import nextstep.qna.CannotDeleteException; +import nextstep.users.domain.NsUser; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +public class Answers { + private final List answers; + + public Answers() { + this(new ArrayList<>()); + } + + public Answers(Answer answer) { + this(List.of(answer)); + } + + public Answers(List answers) { + this.answers = answers; + } + + + public List getAnswers() { + return this.answers; + } + + public void add(Answer answer) { + this.answers.add(answer); + } + + public List delete() { + List deleteHistories = new ArrayList<>(); + + for (Answer answer : answers) { + answer.delete(); + deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now())); + } + + return deleteHistories; + } + + public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { + for (Answer answer : answers) { + answer.validateDeletableBy(loginUser); + } + } +} diff --git a/src/main/java/nextstep/qna/domain/Question.java b/src/main/java/nextstep/qna/domain/Question.java index 7475333805..299588f7be 100644 --- a/src/main/java/nextstep/qna/domain/Question.java +++ b/src/main/java/nextstep/qna/domain/Question.java @@ -6,6 +6,8 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class Question { private Long id; @@ -16,7 +18,7 @@ public class Question { private NsUser writer; - private List answers = new ArrayList<>(); + private Answers answers = new Answers(); private boolean deleted = false; @@ -83,7 +85,7 @@ public boolean isDeleted() { } public List getAnswers() { - return answers; + return answers.getAnswers(); } public List delete(NsUser loginUser) throws CannotDeleteException { @@ -95,10 +97,7 @@ public List delete(NsUser loginUser) throws CannotDeleteException deleteHistories.add(new DeleteHistory(ContentType.QUESTION, this.id, this.getWriter(), LocalDateTime.now())); - for (Answer answer : answers) { - answer.setDeleted(true); - deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now())); - } + deleteHistories.addAll(answers.delete()); return deleteHistories; } @@ -108,11 +107,7 @@ public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { throw new CannotDeleteException("질문을 삭제할 권한이 없습니다."); } - for (Answer answer : answers) { - if (!answer.isOwner(loginUser)) { - throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); - } - } + answers.validateDeletableBy(loginUser); } @Override diff --git a/src/test/java/nextstep/qna/domain/AnswerTest.java b/src/test/java/nextstep/qna/domain/AnswerTest.java index 8e80ffb429..df66fedf8f 100644 --- a/src/test/java/nextstep/qna/domain/AnswerTest.java +++ b/src/test/java/nextstep/qna/domain/AnswerTest.java @@ -1,8 +1,20 @@ package nextstep.qna.domain; +import nextstep.qna.CannotDeleteException; import nextstep.users.domain.NsUserTest; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class AnswerTest { public static final Answer A1 = new Answer(NsUserTest.JAVAJIGI, QuestionTest.Q1, "Answers Contents1"); public static final Answer A2 = new Answer(NsUserTest.SANJIGI, QuestionTest.Q1, "Answers Contents2"); + + @Test + void 다른_사람이_쓴_답변이_있어_삭제할_수_없음() { + assertThatThrownBy(()-> + A1.validateDeletableBy(NsUserTest.SANJIGI) + ).isInstanceOf(CannotDeleteException.class) + .hasMessageContaining("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); + } } diff --git a/src/test/java/nextstep/qna/domain/AnswersTest.java b/src/test/java/nextstep/qna/domain/AnswersTest.java new file mode 100644 index 0000000000..2ef1f895c9 --- /dev/null +++ b/src/test/java/nextstep/qna/domain/AnswersTest.java @@ -0,0 +1,14 @@ +package nextstep.qna.domain; + +import nextstep.users.domain.NsUserTest; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +public class AnswersTest { + @Test + void create() { + Answers answers = new Answers(new Answer(11L, NsUserTest.JAVAJIGI, QuestionTest.Q1, "Answers Contents1")); + + Assertions.assertThat(answers.getAnswers()).hasSize(1); + } +} diff --git a/src/test/java/nextstep/qna/domain/QuestionTest.java b/src/test/java/nextstep/qna/domain/QuestionTest.java index 82955165eb..92c1bf9df6 100644 --- a/src/test/java/nextstep/qna/domain/QuestionTest.java +++ b/src/test/java/nextstep/qna/domain/QuestionTest.java @@ -2,7 +2,6 @@ import nextstep.qna.CannotDeleteException; import nextstep.users.domain.NsUserTest; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.*; From 06dc6e1ee8ce797d29d864c2e40e6530826bde96 Mon Sep 17 00:00:00 2001 From: ho-jun97 Date: Wed, 10 Dec 2025 22:08:31 +0900 Subject: [PATCH 3/6] =?UTF-8?q?refactor:=20delete=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=A0=84=EC=97=90=20=EC=9C=A0=ED=9A=A8=ED=95=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/qna/domain/Answer.java | 10 ++---- .../java/nextstep/qna/domain/Answers.java | 4 +-- .../java/nextstep/qna/domain/Question.java | 36 +++---------------- .../java/nextstep/qna/service/QnAService.java | 1 + 4 files changed, 11 insertions(+), 40 deletions(-) diff --git a/src/main/java/nextstep/qna/domain/Answer.java b/src/main/java/nextstep/qna/domain/Answer.java index daa1ab3a9b..ee6395c224 100644 --- a/src/main/java/nextstep/qna/domain/Answer.java +++ b/src/main/java/nextstep/qna/domain/Answer.java @@ -48,13 +48,9 @@ public Long getId() { return id; } - private Answer setDeleted(boolean deleted) { - this.deleted = deleted; - return this; - } - - public void delete() { - setDeleted(true); + public void markAsDeleted(NsUser loginUser) throws CannotDeleteException { + validateDeletableBy(loginUser); + this.deleted = true; } public boolean isDeleted() { diff --git a/src/main/java/nextstep/qna/domain/Answers.java b/src/main/java/nextstep/qna/domain/Answers.java index c6c8cd07c2..45a66da361 100644 --- a/src/main/java/nextstep/qna/domain/Answers.java +++ b/src/main/java/nextstep/qna/domain/Answers.java @@ -31,11 +31,11 @@ public void add(Answer answer) { this.answers.add(answer); } - public List delete() { + public List delete(NsUser loginUser) throws CannotDeleteException { List deleteHistories = new ArrayList<>(); for (Answer answer : answers) { - answer.delete(); + answer.markAsDeleted(loginUser); deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now())); } diff --git a/src/main/java/nextstep/qna/domain/Question.java b/src/main/java/nextstep/qna/domain/Question.java index 299588f7be..4e691bd63c 100644 --- a/src/main/java/nextstep/qna/domain/Question.java +++ b/src/main/java/nextstep/qna/domain/Question.java @@ -6,8 +6,6 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; public class Question { private Long id; @@ -44,24 +42,6 @@ public Long getId() { return id; } - public String getTitle() { - return title; - } - - public Question setTitle(String title) { - this.title = title; - return this; - } - - public String getContents() { - return contents; - } - - public Question setContents(String contents) { - this.contents = contents; - return this; - } - public NsUser getWriter() { return writer; } @@ -75,29 +55,23 @@ public boolean isOwner(NsUser loginUser) { return writer.equals(loginUser); } - public Question setDeleted(boolean deleted) { - this.deleted = deleted; - return this; + public void markAsDeleted(NsUser loginUser) throws CannotDeleteException { + validateDeletableBy(loginUser); + this.deleted = true; } public boolean isDeleted() { return deleted; } - public List getAnswers() { - return answers.getAnswers(); - } - public List delete(NsUser loginUser) throws CannotDeleteException { - validateDeletableBy(loginUser); + this.markAsDeleted(loginUser); List deleteHistories = new ArrayList<>(); - this.setDeleted(true); - deleteHistories.add(new DeleteHistory(ContentType.QUESTION, this.id, this.getWriter(), LocalDateTime.now())); - deleteHistories.addAll(answers.delete()); + deleteHistories.addAll(answers.delete(loginUser)); return deleteHistories; } diff --git a/src/main/java/nextstep/qna/service/QnAService.java b/src/main/java/nextstep/qna/service/QnAService.java index 5d8787aef4..77b4287b51 100644 --- a/src/main/java/nextstep/qna/service/QnAService.java +++ b/src/main/java/nextstep/qna/service/QnAService.java @@ -8,6 +8,7 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.util.List; @Service("qnaService") public class QnAService { From 12e7e60a0b7284cfdbf4c04a14c6b2531303c1b3 Mon Sep 17 00:00:00 2001 From: ho-jun97 Date: Wed, 10 Dec 2025 23:38:57 +0900 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=EA=B3=B5=ED=86=B5=EB=90=9C=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/qna/domain/Answer.java | 50 ++++++------------- .../java/nextstep/qna/domain/BaseEntity.java | 31 ++++++++++++ .../java/nextstep/qna/domain/PostContent.java | 31 ++++++++++++ .../java/nextstep/qna/domain/Question.java | 46 ++++++----------- 4 files changed, 93 insertions(+), 65 deletions(-) create mode 100644 src/main/java/nextstep/qna/domain/BaseEntity.java create mode 100644 src/main/java/nextstep/qna/domain/PostContent.java diff --git a/src/main/java/nextstep/qna/domain/Answer.java b/src/main/java/nextstep/qna/domain/Answer.java index ee6395c224..d561efeff8 100644 --- a/src/main/java/nextstep/qna/domain/Answer.java +++ b/src/main/java/nextstep/qna/domain/Answer.java @@ -5,22 +5,10 @@ import nextstep.qna.UnAuthorizedException; import nextstep.users.domain.NsUser; -import java.time.LocalDateTime; - -public class Answer { - private Long id; - - private NsUser writer; - +public class Answer extends BaseEntity { private Question question; - private String contents; - - private boolean deleted = false; - - private LocalDateTime createdDate = LocalDateTime.now(); - - private LocalDateTime updatedDate; + private PostContent postContent; public Answer() { } @@ -30,8 +18,12 @@ public Answer(NsUser writer, Question question, String contents) { } public Answer(Long id, NsUser writer, Question question, String contents) { - this.id = id; - if(writer == null) { + this(id, question, new PostContent(writer,contents)); + } + + public Answer(Long id, Question question, PostContent postContent) { + super(id); + if(postContent.isWriter()) { throw new UnAuthorizedException(); } @@ -39,34 +31,21 @@ public Answer(Long id, NsUser writer, Question question, String contents) { throw new NotFoundException(); } - this.writer = writer; this.question = question; - this.contents = contents; - } - - public Long getId() { - return id; + this.postContent = postContent; } public void markAsDeleted(NsUser loginUser) throws CannotDeleteException { validateDeletableBy(loginUser); - this.deleted = true; - } - - public boolean isDeleted() { - return deleted; + delete(); } public boolean isOwner(NsUser writer) { - return this.writer.equals(writer); + return this.postContent.isOwner(writer); } public NsUser getWriter() { - return writer; - } - - public String getContents() { - return contents; + return this.postContent.getWriter(); } public void toQuestion(Question question) { @@ -81,6 +60,9 @@ public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { @Override public String toString() { - return "Answer [id=" + getId() + ", writer=" + writer + ", contents=" + contents + "]"; + return "Answer{" + + "question=" + question + + ", postContent=" + postContent + + '}'; } } diff --git a/src/main/java/nextstep/qna/domain/BaseEntity.java b/src/main/java/nextstep/qna/domain/BaseEntity.java new file mode 100644 index 0000000000..414d8575b1 --- /dev/null +++ b/src/main/java/nextstep/qna/domain/BaseEntity.java @@ -0,0 +1,31 @@ +package nextstep.qna.domain; + +import java.time.LocalDateTime; + +public abstract class BaseEntity { + private Long id; + + private LocalDateTime createdDate = LocalDateTime.now(); + + private LocalDateTime updatedDate; + + private boolean deleted = false; + + public BaseEntity() {} + + public BaseEntity(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void delete() { + this.deleted = true; + } + + public boolean isDeleted() { + return deleted; + } +} diff --git a/src/main/java/nextstep/qna/domain/PostContent.java b/src/main/java/nextstep/qna/domain/PostContent.java new file mode 100644 index 0000000000..ad8bed7924 --- /dev/null +++ b/src/main/java/nextstep/qna/domain/PostContent.java @@ -0,0 +1,31 @@ +package nextstep.qna.domain; + +import nextstep.users.domain.NsUser; + +public class PostContent { + private final NsUser writer; + private final String title; + private final String contents; + + public PostContent(NsUser writer, String contents) { + this(writer, "", contents); + } + + public PostContent(NsUser writer, String title, String contents) { + this.writer = writer; + this.title = title; + this.contents = contents; + } + + public NsUser getWriter() { + return this.writer; + } + + public boolean isOwner(NsUser loginUser) { + return writer.equals(loginUser); + } + + public boolean isWriter() { + return writer == null; + } +} diff --git a/src/main/java/nextstep/qna/domain/Question.java b/src/main/java/nextstep/qna/domain/Question.java index 4e691bd63c..e7fe5a1bb5 100644 --- a/src/main/java/nextstep/qna/domain/Question.java +++ b/src/main/java/nextstep/qna/domain/Question.java @@ -7,43 +7,28 @@ import java.util.ArrayList; import java.util.List; -public class Question { - private Long id; - - private String title; - - private String contents; - - private NsUser writer; +public class Question extends BaseEntity { + private PostContent postContent; private Answers answers = new Answers(); - private boolean deleted = false; - - private LocalDateTime createdDate = LocalDateTime.now(); - - private LocalDateTime updatedDate; - public Question() { } public Question(NsUser writer, String title, String contents) { - this(0L, writer, title, contents); + this(0L, new PostContent(writer, title, contents)); } public Question(Long id, NsUser writer, String title, String contents) { - this.id = id; - this.writer = writer; - this.title = title; - this.contents = contents; + this(id, new PostContent(writer, title, contents)); } - - public Long getId() { - return id; + public Question(Long id, PostContent postContent) { + super(id); + this.postContent = postContent; } public NsUser getWriter() { - return writer; + return postContent.getWriter(); } public void addAnswer(Answer answer) { @@ -52,16 +37,12 @@ public void addAnswer(Answer answer) { } public boolean isOwner(NsUser loginUser) { - return writer.equals(loginUser); + return postContent.isOwner(loginUser); } public void markAsDeleted(NsUser loginUser) throws CannotDeleteException { validateDeletableBy(loginUser); - this.deleted = true; - } - - public boolean isDeleted() { - return deleted; + delete(); } public List delete(NsUser loginUser) throws CannotDeleteException { @@ -69,7 +50,7 @@ public List delete(NsUser loginUser) throws CannotDeleteException List deleteHistories = new ArrayList<>(); - deleteHistories.add(new DeleteHistory(ContentType.QUESTION, this.id, this.getWriter(), LocalDateTime.now())); + deleteHistories.add(new DeleteHistory(ContentType.QUESTION, getId(), this.getWriter(), LocalDateTime.now())); deleteHistories.addAll(answers.delete(loginUser)); @@ -86,6 +67,9 @@ public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { @Override public String toString() { - return "Question [id=" + getId() + ", title=" + title + ", contents=" + contents + ", writer=" + writer + "]"; + return "Question{" + + "postContent=" + postContent + + ", answers=" + answers + + '}'; } } From 0c6c63ae53df0ee6d0f4fdc4867a2429046dd894 Mon Sep 17 00:00:00 2001 From: ho-jun97 Date: Thu, 11 Dec 2025 00:12:18 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=EC=82=AD=EC=A0=9C=20=EB=A7=88?= =?UTF-8?q?=ED=81=AC=20=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84=EA=B3=BC=20?= =?UTF-8?q?history=20=EB=A7=8C=EB=93=9C=EB=8A=94=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/qna/domain/Answers.java | 9 +++++++-- .../java/nextstep/qna/domain/Question.java | 18 ++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/java/nextstep/qna/domain/Answers.java b/src/main/java/nextstep/qna/domain/Answers.java index 45a66da361..e5ee4f1000 100644 --- a/src/main/java/nextstep/qna/domain/Answers.java +++ b/src/main/java/nextstep/qna/domain/Answers.java @@ -31,11 +31,16 @@ public void add(Answer answer) { this.answers.add(answer); } - public List delete(NsUser loginUser) throws CannotDeleteException { + public void delete(NsUser loginUser) throws CannotDeleteException { + for (Answer answer : answers) { + answer.markAsDeleted(loginUser); + } + } + + public List createDeleteHistories() { List deleteHistories = new ArrayList<>(); for (Answer answer : answers) { - answer.markAsDeleted(loginUser); deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now())); } diff --git a/src/main/java/nextstep/qna/domain/Question.java b/src/main/java/nextstep/qna/domain/Question.java index e7fe5a1bb5..4b75523e42 100644 --- a/src/main/java/nextstep/qna/domain/Question.java +++ b/src/main/java/nextstep/qna/domain/Question.java @@ -47,14 +47,24 @@ public void markAsDeleted(NsUser loginUser) throws CannotDeleteException { public List delete(NsUser loginUser) throws CannotDeleteException { this.markAsDeleted(loginUser); + answers.delete(loginUser); - List deleteHistories = new ArrayList<>(); + return createDeleteHistories(); + } + + public List createDeleteHistories() { + List histories = new ArrayList<>(); - deleteHistories.add(new DeleteHistory(ContentType.QUESTION, getId(), this.getWriter(), LocalDateTime.now())); + histories.add(new DeleteHistory( + ContentType.QUESTION, + getId(), + getWriter(), + LocalDateTime.now() + )); - deleteHistories.addAll(answers.delete(loginUser)); + histories.addAll(answers.createDeleteHistories()); - return deleteHistories; + return histories; } public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { From 51cd6d2b0487a91512a75bba0f87c00f1a8a0cb8 Mon Sep 17 00:00:00 2001 From: ho-jun97 Date: Fri, 12 Dec 2025 00:56:33 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/qna/domain/Answer.java | 33 +++++++++---------- .../java/nextstep/qna/domain/Answers.java | 11 ++----- .../java/nextstep/qna/domain/BaseEntity.java | 2 +- .../java/nextstep/qna/domain/PostContent.java | 8 ----- .../java/nextstep/qna/domain/Question.java | 8 ++--- .../java/nextstep/qna/service/QnAService.java | 4 ++- .../java/nextstep/qna/domain/AnswerTest.java | 18 +++++++++- .../nextstep/qna/domain/QuestionTest.java | 10 +++++- 8 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/main/java/nextstep/qna/domain/Answer.java b/src/main/java/nextstep/qna/domain/Answer.java index d561efeff8..93d97a80a5 100644 --- a/src/main/java/nextstep/qna/domain/Answer.java +++ b/src/main/java/nextstep/qna/domain/Answer.java @@ -5,10 +5,12 @@ import nextstep.qna.UnAuthorizedException; import nextstep.users.domain.NsUser; +import java.time.LocalDateTime; + public class Answer extends BaseEntity { private Question question; - - private PostContent postContent; + private NsUser writer; + private String contents; public Answer() { } @@ -18,12 +20,8 @@ public Answer(NsUser writer, Question question, String contents) { } public Answer(Long id, NsUser writer, Question question, String contents) { - this(id, question, new PostContent(writer,contents)); - } - - public Answer(Long id, Question question, PostContent postContent) { super(id); - if(postContent.isWriter()) { + if(writer == null) { throw new UnAuthorizedException(); } @@ -31,38 +29,39 @@ public Answer(Long id, Question question, PostContent postContent) { throw new NotFoundException(); } + this.writer = writer; this.question = question; - this.postContent = postContent; + this.contents = contents; } - public void markAsDeleted(NsUser loginUser) throws CannotDeleteException { + public void delete(NsUser loginUser) throws CannotDeleteException { validateDeletableBy(loginUser); - delete(); + markAsDeleted(); } public boolean isOwner(NsUser writer) { - return this.postContent.isOwner(writer); + return this.writer.equals(writer); } public NsUser getWriter() { - return this.postContent.getWriter(); + return this.writer; } public void toQuestion(Question question) { this.question = question; } - public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { + private void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { if (!isOwner(loginUser)) { throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); } } + public DeleteHistory createDeleteHistory() { + return new DeleteHistory(ContentType.ANSWER, getId(), getWriter(), LocalDateTime.now()); + } @Override public String toString() { - return "Answer{" + - "question=" + question + - ", postContent=" + postContent + - '}'; + return "Answer [id=" + getId() + ", writer=" + writer + ", contents=" + contents + "]"; } } diff --git a/src/main/java/nextstep/qna/domain/Answers.java b/src/main/java/nextstep/qna/domain/Answers.java index e5ee4f1000..a445dd3cef 100644 --- a/src/main/java/nextstep/qna/domain/Answers.java +++ b/src/main/java/nextstep/qna/domain/Answers.java @@ -3,7 +3,6 @@ import nextstep.qna.CannotDeleteException; import nextstep.users.domain.NsUser; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -33,7 +32,7 @@ public void add(Answer answer) { public void delete(NsUser loginUser) throws CannotDeleteException { for (Answer answer : answers) { - answer.markAsDeleted(loginUser); + answer.delete(loginUser); } } @@ -41,15 +40,9 @@ public List createDeleteHistories() { List deleteHistories = new ArrayList<>(); for (Answer answer : answers) { - deleteHistories.add(new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), LocalDateTime.now())); + deleteHistories.add(answer.createDeleteHistory()); } return deleteHistories; } - - public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { - for (Answer answer : answers) { - answer.validateDeletableBy(loginUser); - } - } } diff --git a/src/main/java/nextstep/qna/domain/BaseEntity.java b/src/main/java/nextstep/qna/domain/BaseEntity.java index 414d8575b1..6ca0168e24 100644 --- a/src/main/java/nextstep/qna/domain/BaseEntity.java +++ b/src/main/java/nextstep/qna/domain/BaseEntity.java @@ -21,7 +21,7 @@ public Long getId() { return id; } - public void delete() { + protected void markAsDeleted() { this.deleted = true; } diff --git a/src/main/java/nextstep/qna/domain/PostContent.java b/src/main/java/nextstep/qna/domain/PostContent.java index ad8bed7924..6df462c9ca 100644 --- a/src/main/java/nextstep/qna/domain/PostContent.java +++ b/src/main/java/nextstep/qna/domain/PostContent.java @@ -7,10 +7,6 @@ public class PostContent { private final String title; private final String contents; - public PostContent(NsUser writer, String contents) { - this(writer, "", contents); - } - public PostContent(NsUser writer, String title, String contents) { this.writer = writer; this.title = title; @@ -24,8 +20,4 @@ public NsUser getWriter() { public boolean isOwner(NsUser loginUser) { return writer.equals(loginUser); } - - public boolean isWriter() { - return writer == null; - } } diff --git a/src/main/java/nextstep/qna/domain/Question.java b/src/main/java/nextstep/qna/domain/Question.java index 4b75523e42..40de23cddc 100644 --- a/src/main/java/nextstep/qna/domain/Question.java +++ b/src/main/java/nextstep/qna/domain/Question.java @@ -42,14 +42,12 @@ public boolean isOwner(NsUser loginUser) { public void markAsDeleted(NsUser loginUser) throws CannotDeleteException { validateDeletableBy(loginUser); - delete(); + markAsDeleted(); } - public List delete(NsUser loginUser) throws CannotDeleteException { + public void delete(NsUser loginUser) throws CannotDeleteException { this.markAsDeleted(loginUser); answers.delete(loginUser); - - return createDeleteHistories(); } public List createDeleteHistories() { @@ -71,8 +69,6 @@ public void validateDeletableBy(NsUser loginUser) throws CannotDeleteException { if (!isOwner(loginUser)) { throw new CannotDeleteException("질문을 삭제할 권한이 없습니다."); } - - answers.validateDeletableBy(loginUser); } @Override diff --git a/src/main/java/nextstep/qna/service/QnAService.java b/src/main/java/nextstep/qna/service/QnAService.java index 77b4287b51..6bed774c65 100644 --- a/src/main/java/nextstep/qna/service/QnAService.java +++ b/src/main/java/nextstep/qna/service/QnAService.java @@ -25,6 +25,8 @@ public class QnAService { public void deleteQuestion(NsUser loginUser, long questionId) throws CannotDeleteException { Question question = questionRepository.findById(questionId).orElseThrow(NotFoundException::new); - deleteHistoryService.saveAll(question.delete(loginUser)); + question.delete(loginUser); + + deleteHistoryService.saveAll(question.createDeleteHistories()); } } \ No newline at end of file diff --git a/src/test/java/nextstep/qna/domain/AnswerTest.java b/src/test/java/nextstep/qna/domain/AnswerTest.java index df66fedf8f..da73246e36 100644 --- a/src/test/java/nextstep/qna/domain/AnswerTest.java +++ b/src/test/java/nextstep/qna/domain/AnswerTest.java @@ -4,6 +4,9 @@ import nextstep.users.domain.NsUserTest; import org.junit.jupiter.api.Test; +import java.time.LocalDateTime; + +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class AnswerTest { @@ -13,8 +16,21 @@ public class AnswerTest { @Test void 다른_사람이_쓴_답변이_있어_삭제할_수_없음() { assertThatThrownBy(()-> - A1.validateDeletableBy(NsUserTest.SANJIGI) + A1.delete(NsUserTest.SANJIGI) ).isInstanceOf(CannotDeleteException.class) .hasMessageContaining("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); } + + @Test + void 답변_삭제_성공() throws CannotDeleteException { + A1.delete(NsUserTest.JAVAJIGI); + + assertThat(A1.isDeleted()).isTrue(); + } + + @Test + void 삭제한_히스토리_생성() { + assertThat(A1.createDeleteHistory()) + .isEqualTo(new DeleteHistory(ContentType.ANSWER, A1.getId(), A1.getWriter(), LocalDateTime.now())); + } } diff --git a/src/test/java/nextstep/qna/domain/QuestionTest.java b/src/test/java/nextstep/qna/domain/QuestionTest.java index 92c1bf9df6..8179985c3d 100644 --- a/src/test/java/nextstep/qna/domain/QuestionTest.java +++ b/src/test/java/nextstep/qna/domain/QuestionTest.java @@ -13,7 +13,7 @@ public class QuestionTest { @Test void 삭제할_수_없는_유저일_때() { assertThatThrownBy(()-> - Q1.validateDeletableBy(NsUserTest.SANJIGI) + Q1.delete(NsUserTest.SANJIGI) ).isInstanceOf(CannotDeleteException.class) .hasMessageContaining("질문을 삭제할 권한이 없습니다."); @@ -21,8 +21,16 @@ public class QuestionTest { @Test void 질문_삭제_성공() throws CannotDeleteException { + Q1.addAnswer(AnswerTest.A1); Q1.delete(NsUserTest.JAVAJIGI); assertThat(Q1.isDeleted()).isTrue(); } + + @Test + void 삭제_히스토리_생성() { + Q1.addAnswer(AnswerTest.A1); + + assertThat(Q1.createDeleteHistories()).hasSize(2); + } }