주문 완료 이벤트
주문하기가 완료되면 여러 후속 작업들이 이뤄진다.
가게에 알림을 보낸다던지 여러 후속 작업들이 필요할 수 있다.
이때 도메인 이벤트를 사용하지 않고 코드를 구현해보면 다음과 같다.
// 응용 서비스
public class OrderService {
// codes...
public void placeOrder(long ordererId, OrderRequest orderRequest) {
Order order = orderMapper.mapFrom(ordererId, orderRequest);
order.place(orderValidator);
orderRepository.save(order);
// 주문 완료 후 후속 작업들
storeService.notifyPlaceOrder(order);
}
}
위 코드를 보면 OrderService에서 StoreService에 의존 관계가 생기게 되고
주문 완료 후 후속 작업들이 많아지게 되면 OrderService에서 더 많은 의존 관계들이 생겨난다.
그리고 StoreService 혹은 다른 의존 관계가 생긴 서비스에서 변경이 일어나면 OrderService에도 영향이 끼치게 된다.
이러한 강한 결합도를 낮추기 위한 방법으로 이벤트 발행-구독 모델을 사용하면 된다.
스프링에서 제공하는 기능으로 도메인에서 AbstractAggregateRoot를 상속 받으면 간편하게 도메인 안에서 이벤트를 발행 할 수 있다.
주문 완료 시 도메인 이벤트를 발생하는 코드는 다음과 같다.
public class Order extends AbstractAggregateRoot {
// codes...
// 주문하기
public void place(OrderValidator orderValidator) {
orderValidator.validate(this);
this.status = Status.ORDERED;
// 이벤트 발행
registerEvent(new OrderPlacedEvent(this));
}
}
public class OrderPlacedEvent {
private Order order;
public OrderPlacedEvent(Order order) {
this.order = order;
}
}
이렇게 작성하면 주문 응용서비스에서는 주문 하기 완료 후 후속 작업들에 대한 코드가 필요 없어진다.
public class OrderService {
// codes...
public void placeOrder(long ordererId, OrderRequest orderRequest) {
Order order = orderMapper.mapFrom(ordererId, orderRequest);
order.place(orderValidator);
orderRepository.save(order);
// 후속 작업들에 대한 코드 필요 없음
}
}
주문 하기 완료 후 이뤄져야 하는 후속 작업들은 주문 하기에서 발생된 주문완료 이벤트를 구독받아서 구현하면 된다.
스프링에서 제공하는 이벤트 리스너를 사용하면 다음과 같이 간편하게 구현이 가능하다.
package com.example.dddstudy.store.application; // 주문 패키지와 다른 가게 패키지
public class OrderPlacedEventHandler {
@EventListener
public void handle(OrderPlacedEvent event) {
System.out.println("주문이 들어왔습니다.");
}
}
가게 응용 서비스 영역에서 주문완료 이벤트를 구독받아 구현한 것이다.
또한 다른 곳에서도 주문완료 이벤트를 구독받아서 후속 작업을 구현 할 수 있다.
이렇게 하게되면 결국 주문에서 가게나 다른 도메인에 결합도를 낮추게 되는 효과를 얻을 수 있다.