【发布时间】:2021-06-30 15:42:58
【问题描述】:
也许我可能对一些基本原则感到困惑或误解。在基于 Axon 的事件溯源项目中应用 DDD 时,您定义了多个聚合,每个聚合具有多个命令处理程序方法来验证聚合的状态更改是否有效,以及应用每个请求的状态更改的相应事件处理程序方法集合。
编辑开始: 所以聚合可能看起来像
@Aggregate
public class Customer {
@AggregateIdentifier
private CustomerId customerId;
private Name name;
@CommandHandler
private Customer(CreateCustomerCommand command) {
AggregateLifecycle.apply(new CustomerCreatedEvent(
command.getCustomerId(), command.getName());
}
@EventSourcingHandler
private void handleEvent(CustomerCreatedEvent event) {
this.customerId = event.getCustomerId();
this.name = event.getName();
}
}
编辑结束
所以我的第一个问题是:我是否正确得出这样的结论:聚合没有直接实现任何状态更改方法(典型的公共方法会更改聚合实例的属性),但是所有状态更改方法都定义在与交互的单独域服务中Axon 的命令网关?
编辑开始: 换句话说,聚合是否应该定义负责向框架发送命令的 setter,这将导致通过将以下代码添加到聚合来调用相应的命令处理程序和事件处理程序?
public void setName(String name){
commandGateway.send(new UpdateNameCommand(this.customerId, name));
}
@CommandHandler
private void handleCommand(UpdateNameCommand command) {
AggregateLifecycle.apply(new NameUpdatedEvent(command.getCustomerId(), command.getName());
}
@EventSourcingHandler
private void handleEvent(NameUpdatedEvent event) {
this.name = event.getName();
}
这似乎违反了一些建议,因为需要从聚合中引用网关。
或者您通常会在单独的服务类中定义此类方法,然后将命令发送到框架。
@Service
public class CustomerService {
@Autowired
private CommandGateway gateway;
public void createCustomer(String name) {
CreateCustomerCommand command = new CreateCustomerCommand(name);
gateway.send(command);
}
public void changeName(CustomerId customerId, String name) {
UpdateNameCommand command = new UpdateNameCommand (customerId, name);
gateway.send(command);
}
}
这对我来说似乎是正确的方法。这似乎使得(至少在我看来)外部世界无法直接访问聚合的行为(所有命令和事件处理程序方法都可以设为私有),就像一个更“传统”的对象,它们是请求状态更改的入口点...
编辑结束
其次:这是否与定义其(公共)接口方法以与之交互的每个类的 OOP 原则相矛盾?换句话说,这种方法是不是让一个对象或多或少成为一个无法直接交互的转储对象?
感谢您的反馈, 库尔特
【问题讨论】:
标签: oop domain-driven-design event-sourcing axon