Skip to content

[calendar] 애그리게잇의 양방향 의존성 제거 ( + 리팩토링 방법 ) #105

Description

@hwicode

캘린더 패키지에서 애그리게잇의 의존성을 잘 못 관리하여 이를 수정함

수정 전

캘린더가 애그리게잇 루트인 애그리게잇

캘린더가 애그리게잇 루트로 구현한 이유

  • 목표를 추가할 때, 캘린더에 존재하는 목표와 이름이 중복되면 안된다.
  • 목표의 이름을 변경할 때도 캘린더의 다른 목표들과 이름이 중복되면 안된다.
  • 캘린더 내부에 캘린더의 목표들이 존재하고, 중복 여부를 판단한다.

목표가 애그리게잇 루트인 애그리게잇

목표가 애그리게잇 루트로 구현한 이유

  • 서브 목표의 상태에 따라 목표의 상태가 달라질 수 있기 때문에 서브 목표의 처리를 목표에서 진행한다.
  • 목표가 삭제되면 캘린더에 존재하는 목표들도 삭제되어야 한다.

문제점

  • 그림을 보면 애그리게잇들이 분리되어 있는 게 아니라 포함되어 있는 관계를 가진다.
  • 이는 의존성을 잘 못 관리된 것으로 볼 수 있다.

수정 후

애그리게잇 분리할 때 고려한 점

  • 겹쳐져 있는 애그리게잇을 분리해야 한다.
  • 목표의 상태와 서브 목표의 상태는 서로 영향을 미치므로, 일관성 유지하기 위해 하나의 애그리게잇에 존재해야 한다.
  • 목표과 CalendarGoal의 생명 주기는 동일하기 때문에 하나의 애그리게잇으로 만들어줬다.
  • 캘린더에 목표를 추가하기 위해서는 CalendarGoal이 필요하지만 의존성을 분리해주기 위해 다른 애그리게잇으로 만들었다.

캘린더를 위한 도메인 서비스

  • 목표를 추가 또는 이름을 변경할 때 캘린더의 목표들을 통해 중복 검사를 해야 한다.
  • 하지만 캘린더와 캘린더의 목표는 서로 다른 애그리게잇이므로 도메인 서비스를 통해 로직을 처리해야 한다.
  • 목표가 애그리게잇 루트이므로, 캘린더와 목표를 통해 도메인 서비스에서 로직을 처리했다.
추가 설명

GoalRepository의 findAllByCalendar() 메서드 구현 과정

목표를 어디서 가져와야 할까?

  • 목표를 가져오는 것은 인프라 계층의 역할이라고 생각함
  • 목표를 조회하는 기능이므로 GoalRepository에서 조회한다.

어떻게 하면 캘린더와 연관된 목표를 가져올 수 있을까?

  • 캘린더에 연관된 목표들을 가져와야 한다. ex) 1월의 목표 리스트
  • CalendarGoalRepository에서 캘린더에 해당하는 CalendarGoal을 조회한다.
  • 그리고 CalendarGoal을 Goal로 변환해서 리턴한다.

GoalRepository에서 캘린더와 연관된 목표를 가져오는 방법은?

  • Spring Data JPA를 활용하여 GoalRepository를 사용자 정의 레포지토리로 확장했다.
  • 사용자 정의 레포지토리는 CalendarGoalRepository에서 CalendarGoal를 조회하고 Goal로 변환해서 리턴하는 기능 구현

도메인 서비스의 구현 과정

  • 수정 전에 캘린더에 있었던 기능들을 도메인 서비스로 옮겼다.
  • 애그리게잇이 필요하면 애그리게잇 루트를 조회해야 한다.
  • 그래서 캘린더에 있을 때는 CalendarGoal을 이용한 로직들을 Goal로 수정했다.



리팩토링을 진행하면서 느낀 효율적인 방법

리팩토링을 실패한 과정

  • 처음에 리팩토링은 진행할 때, 뭐부터 손을 대야 할지 잘 몰라서 문제가 보일 때마다 수정을 진행했다.
  • 한 번에 여러 개의 문제들을 건들다 보니 변경되는 클래스들이 점점 많아지고 무엇 때문에 변경되었는지 구분하기 어려워졌다.
  • 결국 변경한 모든 것을 초기화하고 다시 시작했다.

리팩토링을 성공한 과정

  • 리팩토링할 기능 발견
  • 원하는 방식으로 로직을 작성(이전 코드는 아직 삭제하지 않음)
  • 작성한 로직에 테스트 코드를 작성
  • 새로 작성한 코드로 의존성을 옮기기 전에 작업이 제대로 동작하는지 아닌지 판별할 수 있는 테스트 작성
  • 리팩토링한 코드로 의존성을 옮기고 테스트를 진행하여 제대로 동작하는지 확인
  • 제대로 동작한다면 이전의 코드를 삭제하고, 잘 못 동작하면 이전 코드 분석

분석

  • 리팩토링을 실패했을 때의 가장 큰 문제는 한 번에 너무 여러 가지를 하려고 했던 점이다.
  • 생각 없이 보이는 문제마다 건들다 보니 뭐가 뭔지 구분하지 못하고 머릿속이 복잡해졌다.
  • 이와 달리 한 번에 하나의 문제만 건들였을 때는 클래스의 변경 이유가 하나만 존재한다.
  • 그래서 단계적으로 문제를 해결할 수 있었다.
  • 너무 복잡해서 어떻게 해야 할지 모르겠다면, 문제를 단계별로 나누고 하나씩 진행해보는 게 좋은 방식인 것 같다.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions