도메인 주도 개발 시작하기: 7. 도메인 서비스

ParkIsComing·2023년 4월 3일
0

7.1 여러 애그리거트가 필요한 기능

  • 한 애그리거트에 넣기 애매한 도메인 기능을 억지로 특정 애그리거트에 구현하면 안 된다.
  • 이럴 때는 도메인 기능을 별도의 서비스로 구현한다.

7.2 도메인 서비스

  • 도메인 서비스는 도메인 영역에 위치한 도메인 로직을 표현할 때 사용한다.
  • 이럴 때 도메인 서비스를 사용하자.
    • 계산 로직: 한 애그리거트에 넣기에는 복잡한 계산 로직
    • 외부 시스템 연동이 필요한 도메인 로직

    1) 계산 로직과 도메인 서비스

  • 한 애그리거트에 넣기 애매한 도메인 개념은 도메인 서비스를 이용해 표현한다.
  • 도메인 서비스는 상태 없이 로직만 구현한다.

❤️도메인 서비스 : DiscountCalculationService

//할인 금액 계산은 Money에 넣기도 애매하니까 도메인 서비스를 만들어서 넣는다.

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(Orderer.getMember().getGrade());
         
         return couponDiscount.add(memberShipDiscount);
      
      
   }
   
   private Money calculateDiscount(Coupon coupon){
       ...
   }
   
   private Money calculateDiscount(MemberGrade grade){
   		...
   }
}

❤️애그리거트 또는 응용서비스가 도메인 서비스를 사용할 수 있다.

// 이 경우 Order 애그리거트의 [결제 금액 계산 기능]에 전달하였으므로 애그리거트가 사용 주체이다.

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);
   
   }
   
}

❤️ 애그리거트 객체에 도메인 서비스를 전달하는 것은 응용 서비스 책임이다.

public class OrderService {
	private DiscountCalculationService discountCalcultionService;
   
   @Transactional
   public OrderNo placeOrder(OrderRequest orderRequest){ 	//주문요청 정보 input
   	OrderNo orderNo = orderRepository.nextId(); 		//주문번호도 객체로 만들었음
       Order order = createORder(orderNo, orderRequest) 	//주문 객체 생성
       orderRepository.save(order);
       return orderNo;
   }
   
   private Order createOrder(OrderNo orderNo, OrderRequest orderReq){
   	Member member = findMember(orderReq.getOrderId());
       Order order = new Order(orderNo, orderReq.getOrderLines(), orderReq.getCoupons(),
       createOrderer(member), orderReq.getShippingInfo());
       order.calculateAmounts(this.discountCalculationService, member.getGrade());
       return order;
   }
}

❤️ 도메인 서비스는 도메인 로직을 수행하지 응용 로직을 수행하지는 않는다.
❤️ 트랜잭션 처리와 같은 로직은 응용 로직 -> 응용 서비스에서 처리해야

2) 외부 시스템 연동과 도메인 서비스

❤️ 외부 시스템이나 타 도메인과의 연동 기능도 도메인 서비스가 될 수 있다.

3) 도메인 서비스의 패키지 위치

  • 도메인 서비스는 다른 도메인 구성요소(like Order, OrderRepository)와 동일한 패키지에 위치한다.

0개의 댓글