[Book] 도메인 주도 개발 시작하기 - 최범균 지음

최범균 - 도메인 주도 개발 시작하기

개인적으로 참고할 부분 메모

1장. 도메인 모델 시작하기

  • 도메인 모델을 표현할 때 클래스 다이어그램이나 상태 다이어그램과 같은 UML 표기법만 사용해야 하는 것은 아님.
    • 관계가 중요 : 그래프 활용.
    • 계산 규칙 중요 : 수학 공식 활용
    • 도메인을 이해하는 데 도움이 된다면 표현 방식이 무엇인지는 중요 X
  • 하위 도메인 & 모델
    • 같은 용어라도 하위 도메인마다 의미가 다를 수 있음
    • 각 하위 도메인마다 별도로 모델 생성해야
  • 프로젝트 초기 : 개요 수준 개념 모델
    • 전체 윤곽 이해에 집중
    • 구현 과정 : 개념 모델 -> 구현 모델로 발전
  • 도메인 모델 도출
    • 핵심 구성요소, 규칙, 기능 찾아 도메인 모델 도출
    • 도메인 관점에서 코드가 도메인 잘 표현해야
      • eg) 메소드명을 단순하게 update라고 표현 지양 -> 도메인 의미가 담긴 메소드 작명 필요
  • 유비쿼터스 언어 사용하기
    • 도메인 용어에 알맞는 단어 찾는 시간을 아까워하지 말자

2장. 아키텍처 개요

  • 고수준 모듈이 저수준 모듈에 의존하지 않도록 한다
    • DIP로 해결 : 테스트 용이 + 구현 교체 용이
  • 도메인 영역 주요 구성 요소
    • 엔티티 : 고유 식별자. 도메인 관련 기능 제공
    • 벨류 : 하나의 값
    • 애그리거트 : 연관된 엔티티와 밸류 객체를 하나로 묶은 개념
    • 리포지토리 : 영속성 처리
    • 도메인 서비스 : 특정 엔티티에 속하지 않은 도메인 로직 구현.

3장. 애그리거트

  • 애그리거트 루트가 제공하는 메서드는 도메인 규칙에 따라 애그리거트에 속한 객체의 일관성이 깨지지 않도록 구현
  • 한 트랜잭션에 한 개의 애그리거트만 수정
    • 다른 애그리거트 수정 : 도메인 이벤트 활용
  • 애그리거트 간의 참조는 ID를 이용한 참조 활용
    • ID 참조 방식으로 인한 N+1 조회 문제는 조회 전용 쿼리 통해 해결
  • 애그리거트가 갖고 있는 데이터를 이용해서 다른 애그리거트를 생성해야 한다면 애그리거트에 팩토리 메서드를 구현하는 것을 고려
    • eg) 상점(Store) 애그리거트에서 상품(Product) 생성 팩토리 메서드(Store.createProduct()) 제공
      public class Store {
      public Product createProduct(ProductId newProudctId, ProductInfo pi) {
        return ProductFactory.create(newProductId, getId(), pi);
      }
      }
      

4장. 리포지터리와 모델 구현

  • 하나의 테이블에 매핑
    • Entity 는 @Entity 활용. Value Object는 @Embeddable
    • JPA에서 @Entity와 @Embeddable로 클래스 매핑하려면 VO는 기본 생성자 제공 필수
  • 밸루 컬렉션 : 별도 테이블 매핑
    @Entity
    public class Order {
      @EmbeddedId
      private OrderNo order;
    
      @ElementCollection(fetch = FetchType.EAGER)
      @CollectionTable(name = "order_line", joinColumns = @JoinColumn(name = "order_number"))
      @OrderColumn(name = "line_idx")
      private List<OrderLine> orderLines;
    }
    
    @Embeddable
    public class OrderLine {
      @Embedded
      private ProductId productId
    
      @Column(name = "price")
      private Money price;
    }
    
  • 밸류 컬렉션 : 한 개 칼럼 매핑 -> AttributeConverter 활용
  • 하이버네이트는 @Embeddable 타입에 대한 컬렉션의 clear() 메서드를 호출하면 컬랙션에 속한 객체를 로딩하지 않고 한 번의 delete 쿼리로 삭제 처리
    • @Entity & @OneToMany 조합 clear() : select 쿼리 1 + delete 쿼리 n 번 수행
  • 영속성 전파
    • @Embeddable : 함께 저장, 삭제
    • 애그리거트 내 @Entity 타입 : CascadeType.PERSIST, CascadeType.REMOVE 설정

5장. 스프링 데이터 JPA를 이용한 조회 기능