[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); } }
- eg) 상점(Store) 애그리거트에서 상품(Product) 생성 팩토리 메서드(Store.createProduct()) 제공
4장. 리포지터리와 모델 구현
- 하나의 테이블에 매핑
- Entity 는
@Entity
활용. Value Object는@Embeddable
- JPA에서 @Entity와 @Embeddable로 클래스 매핑하려면 VO는 기본 생성자 제공 필수
- Entity 는
- 밸루 컬렉션 : 별도 테이블 매핑
@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
설정