【问题标题】:How to deal with updating Entity (CRUD) and Domain Events using DDD?如何使用 DDD 处理更新实体 (CRUD) 和域事件?
【发布时间】:2017-07-04 17:41:47
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: domain-driven-design cqrs domain-events anemic-domain-model dddd


    【解决方案1】:

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

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

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

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

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

    对于非贫乏的领域模型,您确实会在任务更新中定义事件(数据模型中的事件仍将与任务的状态分开)。

    【讨论】:

    • “使用不贫血的域模型,您确实会在任务更新中定义事件”,非贫血模型的代码是什么?我的意思是如何同时更新多个字段,这是否是个好主意?
    【解决方案2】:

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

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

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

    【讨论】:

    • 我对这里的细节了解得不够多,无法判断您回答的技术质量。但是你想减少一点文字墙的印象吗?在这里和那里使用换行符。也许创建更短、更容易阅读的句子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2015-10-02
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多