DDD 세레나데 5주차 강의 정리

DDD 세레나데 5주차

4주차 복습

  • 비즈니스 로직 수행은 어느 곳에 하는 것이 좋을까 ?
    • 도메인 레이어에서 기능을 수행하고 다른 응용 및 표현 레이어에서 해당 기능을 사용한다.
  • 응용 서비스
    • 사용자의 요청에 맞는 도메인 모델을 찾아오고 그 모델의 로직을 위임하는 처리를 한다.
  • 도메인 서비스
    • 응용 서비스와 도메인 서비스를 판단 하는 기준
      • 두개 이상의 애그리거트가 사용될때
      • 다루고 있는 로직이 위키나 지라에 정리를 해야할 필요성이 있는 경우
      • 두가지 조건을 한줄로 요약하면 도메인 지식이 다른곳으로 흘러가는것을 막아주는 역할을 한다.
      • 도메인 서비스는 어플리케이션 레이어와 도메인 레이어 사이에 위치한다.
  • 응용 서비스의 구현
  • vo가 dto로 돌아다녀 외부에 노출된다면 캡슐화가 깨지는것이 아닌가 ?
    • vo가 dto로 돌아다니는 것은 일종의 trade-off이다.
    • vo의 접근 제어자를 default로 두어 도메인 패키지 내부에서만 사용할수 있도록 만드는것도 하나의 방법이다.
  • 항상 DTO를 만드는것은 실용적이지 않아 DTO를 대신 할 수 있는 VO를 찾는것도 방법이다.
  • 고수준 모듈 저수준 모듈
    • 고수준 모듈이 저수준 모듈에 의존하는것이 아니고 저수준 모듈이 고수준 모듈에 의존하도록 dip를 적용해야 한다.
  • 클린 아키텍처
    • 안에선 밖을 모르고 밖에선 안을 알수 있는 아키텍처
    • 도메인 모델을 외부로 부터 지키는 것이 중요하다.
  • anticorruption layer
    • anticorruption layer 하는 역할이 크다면 별도의 레이어로 만들수도 있고 클래스로도 만들 수 있다.
    • 많은 mapper class assemblr pattern이 등장 하더라도 나의 도메인 모델을 지킬 수 있다.
  • 도메인 서비스 구현 방법
    • 응용 서비스에서 도메인 서비스를 주입 받고 응용서비스 내부에서 메시지를 전달한다.
    • 해당 도메인 서비스에서는 도메인들을 가지고 와서 실제 로직을 실행하는 과정을 거친다.
    • repository는 domain service에 담고 있다.
    • repository에서 실행하는 save와 같은 데이터 추가는 실제로 DB에 값이 저장되지는 하지만 도메인 입장에서는 add와 같은 기능을 한다고 생각하여 repository가 infra영역이 아닌 domain 영역에 있다고 본다.
    • Domain layer가 필요 없는 상황 (하나의 도메인만 사용한다면) application layer에서 처리
    • 도메인 모델에서 에러 같은 경우는 try - catch하여 상위 레이어에 노출되지 않도록 막아준다.
      • 상위 레이어에서 알 수 있는 에러를 핸들링 할수 있도록 하는 것.
  • DTO 가이드
    • dto를 도메인으로 전환하고 도메인을 dto로 전환하는건 application service에서 담당하는것이 맞다.
    • dto가 데이터를 담아서 전달 할 수 있는 영역은 application service까지 이다.
  • 모놀리식 아키텍처는 다른 패키지의 서비스를 주입 받아서 사용하지만 마이크로 서비스로 분리 되는 경우 변경이 힘들다.
  • 외부 컨텍스트에서 발생한 예외 또한 내부 컨텍스트에서 이해할 수 있는 에러로 감싸주어야 한다.
  • infrastructure layer가 anti corruption layer 역할을 할 수도 있다.
  • exception은 domain 패키지에 위치
  • anticorruptionlayer 도메인 내부 에그리게잇 폴더에 위치
  • order - buyer 예시에선 order 에그리게잇이 root가 되었다. 내부에 order , order item entity를 가지고 있고 vo 도 가지고 있다.

전술적 설계 - Domain Event

  • 이벤트란 도메인 전문가가 관심을 가질 법한 것들 (단순 조회 제외)
  • 강한 결합
  • 이벤트
    • 이벤트는 어떤 상태가 변경되었다는것이다.
    • 도메인 모델에서 이벤트를 관리 하는 주체는 에그리게잇이 될 수 있다.
    • 이벤트 핸들러는 이벤트에 담긴 주체를 가지고 부가적인 행동을 하게 된다.
    • 스프링에선 application event publisher 가 트랜잭션이 종료될때 이벤트를 발행 해 준다.
      • 테스트 코드에선 이벤트가 발행되었는지 안되었는지만 확인 하면 된다.
    • 스프링 이벤트는 기본적으로 한 트랜젝션 내부에선 묶여있다.
      • 하나가 실패하면 롤백되는 구조이다.
      • TransactionalEventListener 를 사용하면 트랜잭션이 끝난 후 동작하도록 사용할 수 있다.
    • 스프링 이벤트를 사용하지 않고 이벤트를 발행 하려면 AbstractAggregateRoot 를 상속 받아 registerEvent()으로 이벤트를 발생할 수 있다. 이떄는 save를 강제로 호출 해줘야 한다.
    • 도메인 내부에 이벤트를 가지고 있어야 한다.
  • 이벤트 소싱
    • 도메인 모델에서 발생하는 모든 이벤트를 기록하는 방법
  • CQRS
    • 상태를 변경하는 명령과 모델의 상태를 조회하는 모델을 분리한 패턴.
    • 커멘트 패키지와 조회 패키지등으로 분리 할 수 있다.