我实现了事件源实体(在域驱动设计中称为聚合).创建富域模型是一种很好的做法.域驱动设计(DDD)建议尽可能将所有与业务相关的事物放入核心实体和价值对象中.
但是,将此类方法与事件采购结合使用时存在一个问题.与事件源系统中的传统方法相比,首先存储事件,然后在构建实体以执行某些方法时应用所有事件.
基于此,最大的问题是在哪里放置业务逻辑.通常,我想有一个方法,如:
public void addNewAppointment(...)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我希望该方法可以确保不违反任何业务规则.如果是这种情况,则会抛出异常.
但是在使用事件采购时,我必须创建一个事件:
Event event = new AppointmentAddedEvent(...);
event store.save(event);
Run Code Online (Sandbox Code Playgroud)
现在,我在存储事件之前探索了两种检查业务规则的方法.
首先,检查应用程序层中的业务规则.DDD中的应用程序层是委托层.实际上,它应该不包含业务逻辑.它应该只委托获取核心实体,调用方法和保存的东西.在此示例中,将违反此规则:
List<Event> events = store.getEventsForConference(id);
// all events are applied to create the conference entity
Conference conf = factory.build(events);
if(conf.getState() == CANCELED) {
throw new ConferenceClosed()
}
Event event = new AppointmentAddedEvent(...);
event store.save(event);
Run Code Online (Sandbox Code Playgroud)
显然,添加到已取消会议的约会的业务规则不应该泄露到非核心组件中.
我知道的第二种方法是将命令的处理方法添加到核心实体:
class Conference {
// ...
public List<Event> process(AddAppointmentCommand command) {
if(this.state == CANCELED) {
throw new ConferenceClosed()
}
return Array.asList(new AppointmentAddedEvent(...));
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,好处是业务规则是核心实体的一部分.但存在违反分离关注原则的情况.现在,该实体负责创建存储在事件存储中的事件.除此之外,实体负责创建事件感觉很奇怪.我可以争论为什么实体可以处理事件.但是,用于存储而不是用于自然发布的域事件的创建感觉是错误的.
你有没有人遇到过类似的问题?你是如何解决这些问题的?
现在,我将使用应用程序服务解决方案中的业务规则.它仍然是一个地方,但它违反了一些DDD原则. …
每当我需要模拟一些http请求时,我的第一个选择就是WireMock(我认为这实际上是标准的),但是今天我发现了一些替代工具-MockWebServer。
WireMock与MockWebServer的优缺点是什么?