[DDD START] 2장 아키텍처 개요
15 Jun 2019고수준 모듈과 저수준 모듈
고수준 모듈이 저수준 모듈에 의존할 때 문제점
- 테스트의 어려움
- 저수준 모듈이 구현이 되어야 고수준 모듈의 테스트가 가능하다.
- 기능 확장의 어려움
- 저수준 모듈의 기능을 변경하게 되면 고수준 모듈도 수정해야 할 수 있다.
DIP (Dependency Inversion Principle)
DIP는 이 문제를 해결하기 위해 저수준 모듈이 고수준 모듈에 의존하도록 바꾼다.
- 추상화한 인터페이스를 사용
public interface RuleDiscounter {
public Money applyRules(Customer customer, List<OrderLine> orderLines);
}
public class CalculateDiscountService {
private RuleDiscounter ruleDiscounter;
public CalculateDiscountService(RuleDiscounter ruleDiscounter) {
this.ruleDiscounter = ruleDiscounter;
}
public Moeny calculateDiscount(List<OrderLine> orderLines, String customerId) {
Customer customer = findCustomer(customerId);
return ruleDiscounter.applyRules(customer, orderLines);
}
...
}
public class DroolsRuleDiscounter implements RuleDiscounter {
private kieContainer kContainer;
public DroolsRuleDiscounter() {
KieServices ks = KieServices.Factory.get();
kContainer = ks.getKieClasspathContainer();
}
@Override
public Moeny applyRule(Customer customer, List<OrderLine> orderLines) {
KieSession kSession = KContainer.newKieSession("");
// 계산 로직
...
}
}
고수준 모듈이 저수준 모듈을 사용하려면 고수준 모듈이 저수준 모듈에 의존해야 하는데, 반대로 저수준 모듈이 고수준 모듈에 의존한다고 해서 Dependency Inversion Principle 이라고 부른다
도메인 영역의 주요 구성요소
Entity
- 고유의 식별자를 갖는다.
- 도메인 모델의 데이터와 관련된 기능을 제공
- 취소를 엔티티에서 처리한다.
Value
- 도메인 객체의 속성을 표현
Aggregate
- 관련된 Entity와 Value객체의 개념적인 묶음
- 예) 주문 Aggregate
- Order Entity
- OrderLine Value
- Orderer Value
- 배송지 정보
Aggregate Root
군집에 속한 객체들을 관리하는 엔티티
- 애그리거트 루트를 통해서 간접적으로 애그리거트 내의 다른 엔티티나 밸류에 접근하게 된다.
- 애그리거트의 내부 구현을 숨겨서 애그리거트 단위로 구현을 캡슐화한다.
- 예)주문 애그리거트
- 주문 에그리거트는 Order를 통해서 ShippingInfo를 변경할 수 있다.
Repository
- 도메인 모델의 영속성을 처리
- 애그리거트 단위로 도메인 객체를 저장하고 조회하는 기능을 정의
Domain Service
- 특정 Entity에 속하지 않은 도메인 로직을 제공
- 예로 할인 금액 계산은 상품, 쿠폰, 회원 등급, 구매 금액 등 여러 Entity와 Value를 필요로 한다. 이 경우 도메인 서비스에서 로직을 구현한다.
인프라스트럭처
- 영속성 처리, 트랜잭션, SMTP 클라이언트, REST 클라이언트 등
- 무조건 인프라스트럭처에 대한 의존을 없애는 것이 좋은것은 아님
- 구현의 편리함
- 예) @Transactional, @Entity, @Table