[DDD] 도메인 서비스

계산 로직과 도메인 서비스

  • 할인 금액 계산과 같이 애그리거트에 포함시키기 애매한 도메인 개념을 구현할 때
  • 도메인 서비스를 사용해서 해당 개념을 명시적으로 표현할 수 있음.
  • 서비스 응용 영역이 어떤 서비스에 대한 로직을 다루는 반면에
    • 도메인 서비스에서는 도메인 로직과 관련되어 있지만 도메인 안에서 처리하기 더 범위가 넓은 개념의 로직을 해당 도메인 서비스 로 옮긴다.

할인 금액 로직을 위한 DiscountCalculationService

public class DiscountCalculationService {
    public Money calculateDiscountAmounts(
        List<OrderLine> orderLines,
        List<Coupon> coupons,
        MemberGrade grade) {
        
        Money couponDiscount = coupons.stream()
            .map(coupon -> calculateDiscount(coupon))
            .reduce(Money(0), (v1, v2) -> v1.add(v2));
        
        Money membershipDiscount = calculateDiscount(grade);
        
        return couponDiscount.add(membershipDiscount);
    }
    
    private Money calculateDiscount(Coupon coupon) {
        // 쿠폰에 따른 할인 금액 계산 로직
    }
    
    private Money calculateDiscount(MemberGrade grade) {
        // 회원 등급에 따른 할인 금액 계산 로직
    }
}
  • 해당 서비스는 내 글이 애그리거트나 응용 서비스에 의해서 사용될 수 있고
  • 예를 들어서 Order 애그리거트가 DiscountCalculationService를 사용하여 결제금액을 계산하는 경우
public class Order {
    public void calculateAmounts(DiscountCalculationService disCalSvc, MemberGrade grade) {
        Money totalAmounts = getTotalAmounts();
        Money discountAmounts = disCalSvc.calculateDiscountAmounts(this.orderLines, this.coupons, grade);
        this.paymentAmounts = totalAmounts.minus(discountAmounts);
    }
    
    // 기타 메서드와 속성
}
  • 도메인 서비스를 애그리거트 객체에 전달하는 것은 응용 서비스의 책임이다.
  • 예를 들어, OrderService 응용 서비스는 주문을 처리하고 DiscountCalculationService를 Order 애그리거트에 전달하여 할인 금액을 계산하도록 할 수 있습니다

도메인 서비스와 애그리거트의 상호작용

  • 도메인 서비스는 도메인 로직을 수행하지만
    • 응용 서비스 수행 XXXX
  • 예를 들어, 계좌 이체 기능에서는 두 개의 계좌 애그리거트가 관여한다.
    • 한 애그리거트는 금액을 출금하고
    • 다른 애그리거트는 금액을 입금합니다.

계좌 이체 도메인 서비스 구현 예시

public class TransferService {
    public void transfer(Account fromAcc, Account toAcc, Money amounts) {
        fromAcc.withdraw(amounts);
        toAcc.credit(amounts);
    }
}

응용 서비스는 두 Account 애그리거트를 구한 뒤, TransferService를 이용하여 계좌 이체 도메인 기능을 실행합니다.

응용 서비스와 도메인 서비스의 역할

트랜잭션 처리와 같은 응용 로직은 도메인 서비스가 아닌

  • 응용 서비스에서 처리해야 한다.
  • 도메인 서비스는 애그리거트의 상태를 변경하거나 상태 값을 계산하는 데 초점을 맞춰야한다.

도메인 서비스 구현 기준

특정 기능이 응용 서비스인지 도메인 서비스인지 판단하기 어려울 때는

해당 로직이 애그리거트의 상태를 변경하거나 상태 값을 계산하는지 검사해야한다.

계좌 이체 로직결제 금액 로직은 애그리거트의 상태를 변경하거나 값을 계산하는 도메인 로직입니다.

하지만 출금 계좌 상태 변경 입금 계좌 상태 변경 의 모든 흐름은 응용 서비스 에서 실행 된느 게 맞다.


Uploaded by N2T