-
Notifications
You must be signed in to change notification settings - Fork 300
🚀 1단계 - 레거시 코드 리팩터링 #790
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
🚀 1단계 - 레거시 코드 리팩터링 #790
Conversation
… 권한 체크 메서드 생성 및 테스트 코드 작성
…어떻게 처리하면 좋을지 고민중) 및 테스트 코드 작성
javajigi
left a comment
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.
드디어 현장과 비슷한 코드인 레거시 코드 리팩터링 미션 진행했군요. 👍
몇 가지 고민해보면 좋겠다 생각하는 부분에 대해 피드백 남겼으니 한번 고민해 보면 좋겠습니다.
| ## 코드 리뷰 | ||
| > PR 링크 : | ||
| ## 나의 학습 목표 |
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.
👍
| @@ -0,0 +1,12 @@ | |||
| # ✔️ PR 전 확인해야될 목록 | |||
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.
👍
| throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); | ||
| } | ||
| } | ||
|
|
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.
현재는 valid와 updateDeleted가 분리되어 구현되어 있음.
이 둘을 하나로 구현하는 아래와 비교했을 때 어느 방식으로 구현하는 것이 더 좋을까?
| public void delete(NsUser loginUser) throws CannotDeleteException { | |
| // 유효성 체크와 삭제 상태로 변경 | |
| } |
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.
이 피드백 반영했는지 확인 필요
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class Answers { |
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.
일급 콜렉션 적용 👍
| } | ||
| } | ||
|
|
||
| public List<DeleteHistory> delete(long questionId) { |
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.
| public List<DeleteHistory> delete(long questionId) { | |
| public List<DeleteHistory> delete() { |
questionid는 Question이 가지고 있음.
굳이 필요없지 않을까?
| } | ||
| } | ||
|
|
||
| public List<DeleteHistory> delete(long questionId) { |
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.
| public List<DeleteHistory> delete(long questionId) { | |
| public void delete(NsUser loginUser) { |
Answer 피드백과 같이 현재 둘로 분리되어 있는 구현과 위와 같이 삭제 권한 체크여부와 deleted 상태 변경 로직을 함께 구현하는 위 접근 방식 중 어느 접근 방식이 좋을지 고민해 보면 어떨까?
|
|
||
| return deleteHistories; | ||
| } | ||
|
|
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.
현재는 delete()에서 상태 변경과 List 생성 후 반환하는 현재 구현과 delete()와 toDeleteHistories()와 같이 상태 변경과 List 반환하는 메서드 두 개로 분리하는 것 중 어느 접근 방식이 좋을까?
| } | ||
|
|
||
|
|
||
|
|
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.
Answers 일급 콜렉션에 대한 단위 테스트도 추가하면 어떨까?
상태를 변경하는 메서드와 삭제 내역을 남기는 history를 분리
refactor : answer 테스트 코드 추가, Question 테스트 코드 내부 수정
|
리뷰해 주신 것과 같이 수정해봤습니다 ! 한 메서드는 하나의 역할만 해야된다는 생각으로 검증하는 로직과 상태를 변경하는 로직이 Service(deleteQuestion)에서 각각 호출 되어야 한다고 생각했습니다.
추가로 피드백 전 수정해 놓은 내용 있는데 확인 못하셨을 것 같아 말씀드립니다 ! |
javajigi
left a comment
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.
BaseModel 분리 인상적이네요. 👍
단, 이 같은 추상 클래스를 분리했을 때 고려해야할 부분 피드백 남겼으니 확인해 보세요.
| return this; | ||
| } | ||
|
|
||
| public void updateDeleted() { |
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.
삭제 상태 변경에 따른 검증을 하는 것을 고려했을 때 private으로 구현해야 안전하지 않을까?
| throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); | ||
| } | ||
| } | ||
|
|
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.
이 피드백 반영했는지 확인 필요
| } | ||
| } | ||
|
|
||
| public void addDeleteAnswerHistory(List<DeleteHistory> deleteHistories) { |
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.
| public void addDeleteAnswerHistory(List<DeleteHistory> deleteHistories) { | |
| public List<DeleteHistory> toDeleteAnswerHistories() { | |
| List<DeleteHistory> deleteHistories = new ArrayList<>(); |
개인적으로 List 콜렉션을 인자로 전달해 저장하는 것보다 위와 같이 해당 메서드에서 직접 생성해 반환하는 것이 다른 객체와의 의존 관계가 발생하지 않기 때문에 선호하는 방법임
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public abstract class BaseModel { |
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.
👍
단, 프로젝트에 모든 컨텐츠는 성격의 데이터는 soft delete 정책을 따른다와 같은 규칙이 있을 경우 deleted 상태를 포함하는 것이 추상화 측면에서 맞음.
이렇게 될 경우 이 BaseModel은 이 규칙을 따르지 않는 Model은 상속할 수 없기 때문에 객체의 이름을 더 구체적으로 작성할 것을 추천
AI에게 프로젝트의 정책을 설명하고 더 적합한 이름을 추천 받아본다.
| public LocalDateTime createdDate = LocalDateTime.now(); | ||
|
|
||
| public LocalDateTime updatedDate; | ||
|
|
||
| public boolean deleted = false; |
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.
| public LocalDateTime createdDate = LocalDateTime.now(); | |
| public LocalDateTime updatedDate; | |
| public boolean deleted = false; | |
| private LocalDateTime createdDate = LocalDateTime.now(); | |
| private LocalDateTime updatedDate; | |
| private boolean deleted = false; |
모든 인스턴스 변수는 가능하면 private으로 구현
| public LocalDateTime createdDate = LocalDateTime.now(); | ||
|
|
||
| public LocalDateTime updatedDate; | ||
|
|
||
| public boolean deleted = false; |
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.
| public LocalDateTime createdDate = LocalDateTime.now(); | |
| public LocalDateTime updatedDate; | |
| public boolean deleted = false; | |
| private boolean deleted = false; |
그럼 상태 값 변경은 어떻게 하나?
protected void deleted() {
this.deleted = true;
}아래와 같이 protected 메서드를 제공하고 자식 클래스에서 호출할 수 있도록 한다.
| @@ -0,0 +1,10 @@ | |||
| package nextstep.qna.domain; | |||
|
|
|||
| public class Contents { | |||
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.
이 객체는 값을 포장하는 것 외에 아무 로직도 없는데 포장하는 것이 의미있을까?
Title 동일
단, title과 contents를 인스턴스 변수를 가지는 QuestionBody와 같은 객체를 분리한다면 의미있을까?
…패키지 내에서 사용 가능하도록 생성
## AI의 추천을 받아 적합한 이름을 선택했습니다. ### 추천 클래스명 1. DeletableModel 2. SoftDeletableModel 3. AuditableModel 해당 클래스는 soft delete 정책을 따르기 때문에 2번의 SoftDeletableModel로 선택
javajigi
left a comment
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.
피드백 반영하느라 수고했어요. 👍
단, 피드백 반영할 때 잘못 이해한 부분이 있어 피드백 남겼으니 2단계 진행할 때 함께 반영해 보세요.
| this.question = question; | ||
| } | ||
|
|
||
| public void validateAnswerOwner(NsUser loginUser) throws CannotDeleteException { |
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.
| public void validateAnswerOwner(NsUser loginUser) throws CannotDeleteException { | |
| public void delete(NsUser loginUser) throws CannotDeleteException { |
삭제 가능 여부를 확인하는 것이 핵심이 아니라 삭제가 핵심이지 않을까?
| return answers; | ||
| } | ||
|
|
||
| public void validateAnswerOwner(NsUser loginUser) throws CannotDeleteException { |
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.
| public void validateAnswerOwner(NsUser loginUser) throws CannotDeleteException { | |
| public void delete(NsUser loginUser) throws CannotDeleteException { |
삭제 가능 여부를 확인하는 것이 핵심이 아니라 삭제가 핵심이지 않을까?
|
|
||
| public class QuestionBody { | ||
|
|
||
| private String value; |
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.
| private String value; | |
| private String title; | |
| private String cotents; |
이 두 개의 값을 가지는 객체를 의미했음
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public abstract class SoftDeletableModel { |
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.
👍
| public Answer setDeleted(boolean deleted) { | ||
| this.deleted = deleted; | ||
| return this; | ||
| private void updateDeleted() { |
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.
굳이 이 메서드 필요없지 않을까?
바로 부모 메서드 호출하면 되지 않을까?
안녕하세요 ! 레거시 코드 리팩터링 1단계 리뷰 요청드립니다 ! 🙇♂️
먼저 호성님의 목표 설정과 체크리스트를 보고 저만의 학습 목표를 작성하여 이번 과정에서 놓쳐서는 안될 부분들을 의식하며, 과제를 진행했습니다.
아직은 기존 코드를 리팩터링하는 것이 서투르고, 어색하게 느껴지지만 이 과정을 통해 많은 것을 배웠으면 좋겠습니다.