域对象不可能猜测任何订阅者的需求。域对象的职责只是生成说明发生了什么的事件。@MikeSW 在这个答案中
这是我的策略:
a) 在查询组件的帮助下发布带有基本字段的事件。
例如,我们正在开发一个酒店评论应用程序。每条评论只有在管理员批准后才能被其他客户查看。
public class CommentApprovedEvent {
private String commentId;
}
并且事件处理程序更新评论查询数据的状态。到目前为止一切顺利。有时稍后,一些进一步的要求会随之而来,例如当评论被批准时,最新批准的评论内容应该被视为酒店的“推荐”评论。
我们确实在评论中有hotelId 和内容。但这一次,我们选择不将它们添加到事件中。相反,我们使用查询在事件处理程序中检索它:
公共类 HotelEventHandler {
public void on(CommentApprovedEvent event) {
CommentDetailDto comment = commentDetailQueryService.
findBy(event.getCommentId());
comment.getHotelId();
comment.getContent();
//update hotel's query data
}
}
有时,甚至不可能将所有相关数据添加到事件中。例如,有时后来,一个新的要求来了:当评论被批准时,评论者应该被奖励一些积分。但我们在评论中没有评论者的完整资料。所以我们再次选择查询。
b) 将大事件拆分成较小的事件。
在这种情况下,我们可以添加新事件而不是新属性。考虑 DDD 示例中的交付案例,交付是货物域中的一个重要值对象,它显示了给定货物的许多方面:
/**
* The actual transportation of the cargo, as opposed to
* the customer requirement (RouteSpecification) and the plan (Itinerary).
*
*/
public class Delivery {//value object
private TransportStatus transportStatus;
private Location lastKnownLocation;
private Voyage currentVoyage;
private boolean misdirected;
private Date eta;
private HandlingActivity nextExpectedActivity;
private boolean isUnloadedAtDestination;
private RoutingStatus routingStatus;
private Date calculatedAt;
private HandlingEvent lastEvent;
.....rich behavior omitted
}
交付指示货物的当前状态,一旦登记了新的货物装卸事件或更改路线规范,就会重新计算:
//non-cqrs style of cargo
public void specifyNewRoute(final RouteSpecification routeSpecification) {
this.routeSpecification = routeSpecification;
// Handling consistency within the Cargo aggregate synchronously
this.delivery = delivery.updateOnRouting(this.routeSpecification, this.itinerary);
}
我想到一开始我需要一个 CargoDeliveryUpdatedEvent,比如:
//cqrs style of cargo
public void deriveDeliveryProgress(final HandlingHistory handlingHistory) {
apply(new CargoDeliveryUpdatedEvent(
this.trackingId, delivery.derivedFrom(routeSpecification(),
itinerary(), handlingHistory);
}
class CargoDeliveryUpdatedEvent {
private String trackingId;
private ..... //same fields in Delivery?
private ..... //add more when requirements evolves?
}
但最后我发现我可以使用更小的事件来更好地揭示意图,比如:
//cqrs style of cargo
public void deriveDeliveryProgress(final HandlingHistory handlingHistory) {
final Delivery delivery = Delivery.derivedFrom(
routeSpecification(), itinerary(), handlingHistory);
apply(new CargoRoutingStatusRecalculatedEvent(this.trackingId,
delivery.routingStatus());
apply(new CargoTransportStatusRecalculatedEvent(this.trackingId,
delivery.routingStatus());
....sends events telling other aspects of the cargo
}
class CargoRoutingStatusRecalculatedEvent{
private String trackingId;
private String routingStatus;
}
class CargoTransportStatusRecalculatedEvent{
private String trackingId;
private String transportStatus;
}
希望这些有所帮助。干杯。