2

我知道 DDD 非常适合基于任务的 UI,但我正在重构一个遗留应用程序,其中我有贫血域模型(许多设置器没有业务逻辑)。

第一步是让它到达模型并添加领域事件。虽然添加用于创建(TaskCreated在构造函数中)和删除(TaskRemoved)模型的事件是一个简单的过程,但我正在努力更新模型。

我们有一个带有 PUT/tasks/{id}端点的 RESTful API。在底层,框架将响应的主体映射到 DTO 对象,然后一一调用 setter:

task.setText('new text');
task.setStartDate(newStartDate);
// and so on

我想在任务更新时收听一些事件,并在例如谷歌日历中更新它。正如您所想象的那样,如果我在每个setter(TextChanged、StartDateChanged)中记录事件并监听所有事件,我最终会收到许多对 Google API 的 API 调用,这不是我想要的。

问题是:我应该如何以正确的方式使用更新操作?我应该setters用一个update(newData)电话替换所有这些电话并在那里只调度一个域事件吗?更新任务后如何只对谷歌日历进行一次API 调用?

4

2 回答 2

0

我更喜欢 one-event-per-set 方式,因为更新操作有时只是一个用例,想象一下,稍后在域中,由于外部流程,您将不得不更改实体的一个字段,您应该有一个代表该用例而不是整个更新的命令。

现在问题出现了:我如何跟踪基于单个用例触发的事件?很简单,使用某种相关标识符,例如可以是请求 ID。

为了实现这一点,您可以使用一个包含域事件的列表,当您保存事务时,您分派事件,因为它们是在相同的逻辑上下文中创建的,所以它们将具有相同的相关 ID。

于 2018-09-26T05:15:13.227 回答
0

我应该如何以正确的方式使用更新操作?

通常的答案是域事件不是您正在修改的对象的一部分,而是在单独的数据结构中描述修改。

对于贫血模型,我希望调用者对事件负责。如果框架只是将 DTO 字段自动映射到任务,那可能不是框架。您希望在代码中能够理解编辑的业务上下文的位置定义事件。换句话说,您可能想要TaskRescheduled而不是TaskUpdated.

在初稿中,您可以在知道保存成功时发布事件。

更健壮的是将事件列表与任务一起保存。这为您提供了有关可靠消息传递的更好故事 - 请参阅 Udi Dahan Reliable Messaging without Distributed Transactions以更好地了解其发展方向。

使用不是贫血的域模型,您确实会在任务更新中定义事件(数据模型中的事件仍将与任务的状态分开)。

于 2017-02-15T21:53:07.500 回答