## 캘린더 패키지에서 애그리게잇의 의존성을 잘 못 관리하여 이를 수정함 ### 수정 전 ##### 캘린더가 애그리게잇 루트인 애그리게잇 <img src="https://github.com/hwicode/schedule/assets/95541996/c2425c20-3338-4112-9d38-91af863d3029" width="400" height="300"/> #### 캘린더가 애그리게잇 루트로 구현한 이유 + 목표를 추가할 때, 캘린더에 존재하는 목표와 이름이 중복되면 안된다. + 목표의 이름을 변경할 때도 캘린더의 다른 목표들과 이름이 중복되면 안된다. + 캘린더 내부에 캘린더의 목표들이 존재하고, 중복 여부를 판단한다. <br> ##### 목표가 애그리게잇 루트인 애그리게잇 <img src="https://github.com/hwicode/schedule/assets/95541996/08298f2f-9185-4199-ad5c-60ead0f56063" width="400" height="300"/> #### 목표가 애그리게잇 루트로 구현한 이유 + 서브 목표의 상태에 따라 목표의 상태가 달라질 수 있기 때문에 서브 목표의 처리를 목표에서 진행한다. + 목표가 삭제되면 캘린더에 존재하는 목표들도 삭제되어야 한다. <br> ### 문제점 + 그림을 보면 애그리게잇들이 분리되어 있는 게 아니라 포함되어 있는 관계를 가진다. + 이는 의존성을 잘 못 관리된 것으로 볼 수 있다. <br> ### 수정 후 <img src="https://github.com/hwicode/schedule/assets/95541996/26740bf8-b360-4c99-862a-fd29772b256c" width="400" height="300"/> #### 애그리게잇 분리할 때 고려한 점 + 겹쳐져 있는 애그리게잇을 분리해야 한다. + 목표의 상태와 서브 목표의 상태는 서로 영향을 미치므로, 일관성 유지하기 위해 하나의 애그리게잇에 존재해야 한다. + 목표과 CalendarGoal의 생명 주기는 동일하기 때문에 하나의 애그리게잇으로 만들어줬다. + 캘린더에 목표를 추가하기 위해서는 CalendarGoal이 필요하지만 의존성을 분리해주기 위해 다른 애그리게잇으로 만들었다. <br> #### 캘린더를 위한 도메인 서비스 + 목표를 추가 또는 이름을 변경할 때 캘린더의 목표들을 통해 중복 검사를 해야 한다. + 하지만 캘린더와 캘린더의 목표는 서로 다른 애그리게잇이므로 도메인 서비스를 통해 로직을 처리해야 한다. + 목표가 애그리게잇 루트이므로, 캘린더와 목표를 통해 도메인 서비스에서 로직을 처리했다. <details> <summary>추가 설명</summary> ### GoalRepository의 findAllByCalendar() 메서드 구현 과정 #### 목표를 어디서 가져와야 할까? + 목표를 가져오는 것은 인프라 계층의 역할이라고 생각함 + 목표를 조회하는 기능이므로 GoalRepository에서 조회한다. <br> #### 어떻게 하면 캘린더와 연관된 목표를 가져올 수 있을까? + 캘린더에 연관된 목표들을 가져와야 한다. ex) 1월의 목표 리스트 + CalendarGoalRepository에서 캘린더에 해당하는 CalendarGoal을 조회한다. + 그리고 CalendarGoal을 Goal로 변환해서 리턴한다. <br> #### GoalRepository에서 캘린더와 연관된 목표를 가져오는 방법은? + Spring Data JPA를 활용하여 GoalRepository를 사용자 정의 레포지토리로 확장했다. + 사용자 정의 레포지토리는 CalendarGoalRepository에서 CalendarGoal를 조회하고 Goal로 변환해서 리턴하는 기능 구현 <br> ### 도메인 서비스의 구현 과정 + 수정 전에 캘린더에 있었던 기능들을 도메인 서비스로 옮겼다. + 애그리게잇이 필요하면 애그리게잇 루트를 조회해야 한다. + 그래서 캘린더에 있을 때는 CalendarGoal을 이용한 로직들을 Goal로 수정했다. </details> <br><br> ## 리팩토링을 진행하면서 느낀 효율적인 방법 #### 리팩토링을 실패한 과정 + 처음에 리팩토링은 진행할 때, 뭐부터 손을 대야 할지 잘 몰라서 문제가 보일 때마다 수정을 진행했다. + 한 번에 여러 개의 문제들을 건들다 보니 변경되는 클래스들이 점점 많아지고 무엇 때문에 변경되었는지 구분하기 어려워졌다. + 결국 변경한 모든 것을 초기화하고 다시 시작했다. <br> #### 리팩토링을 성공한 과정 + 리팩토링할 기능 발견 + 원하는 방식으로 로직을 작성(이전 코드는 아직 삭제하지 않음) + 작성한 로직에 테스트 코드를 작성 + 새로 작성한 코드로 의존성을 옮기기 전에 작업이 제대로 동작하는지 아닌지 판별할 수 있는 테스트 작성 + 리팩토링한 코드로 의존성을 옮기고 테스트를 진행하여 제대로 동작하는지 확인 + 제대로 동작한다면 이전의 코드를 삭제하고, 잘 못 동작하면 이전 코드 분석 <br> #### 분석 + 리팩토링을 실패했을 때의 가장 큰 문제는 한 번에 너무 여러 가지를 하려고 했던 점이다. + 생각 없이 보이는 문제마다 건들다 보니 뭐가 뭔지 구분하지 못하고 머릿속이 복잡해졌다. + 이와 달리 한 번에 하나의 문제만 건들였을 때는 클래스의 변경 이유가 하나만 존재한다. + 그래서 단계적으로 문제를 해결할 수 있었다. + 너무 복잡해서 어떻게 해야 할지 모르겠다면, 문제를 단계별로 나누고 하나씩 진행해보는 게 좋은 방식인 것 같다.
캘린더 패키지에서 애그리게잇의 의존성을 잘 못 관리하여 이를 수정함
수정 전
캘린더가 애그리게잇 루트인 애그리게잇
캘린더가 애그리게잇 루트로 구현한 이유
목표가 애그리게잇 루트인 애그리게잇
목표가 애그리게잇 루트로 구현한 이유
문제점
수정 후
애그리게잇 분리할 때 고려한 점
캘린더를 위한 도메인 서비스
추가 설명
GoalRepository의 findAllByCalendar() 메서드 구현 과정
목표를 어디서 가져와야 할까?
어떻게 하면 캘린더와 연관된 목표를 가져올 수 있을까?
GoalRepository에서 캘린더와 연관된 목표를 가져오는 방법은?
도메인 서비스의 구현 과정
리팩토링을 진행하면서 느낀 효율적인 방법
리팩토링을 실패한 과정
리팩토링을 성공한 과정
분석