❤️도메인 서비스 : 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;
}
}
❤️ 도메인 서비스는 도메인 로직을 수행하지 응용 로직을 수행하지는 않는다.
❤️ 트랜잭션 처리와 같은 로직은 응용 로직 -> 응용 서비스에서 처리해야
❤️ 외부 시스템이나 타 도메인과의 연동 기능도 도메인 서비스가 될 수 있다.