我知道DDD适用于基于任务的用户界面,但我正在重构一个遗留应用程序,我有Anemic Domain Model(许多没有业务逻辑的setter)。
最初的步骤之一是使其达到模型并添加域事件。在添加用于在构造函数中创建(TaskCreated
)和删除(TaskRemoved
)的事件时,模型是一个简单的过程,我正在努力使用更新模型。
我们有一个带有PUT /tasks/{id}
端点的RESTful API。在框架下,框架将响应的主体映射到DTO对象,然后逐个调用setter:
task.setText('new text');
task.setStartDate(newStartDate);
// and so on
我希望在更新任务时听一些事件,并在例如Google日历。
正如你可以成像一样,如果我在每个setter
(TextChanged,StartDateChanged)中记录事件并听取所有这些事件,我最终会对Google API进行许多API调用,这不是我想要的。
问题是:我应该如何以正确的方式使用更新操作?我应该使用setters
次呼叫替换所有update(newData)
次呼叫,并仅在那里发送一个域事件吗?如何在更新任务后仅对Google日历进行一次 API调用?
答案 0 :(得分:0)
我应该如何以正确的方式使用Update操作?
通常的答案是域事件不是您正在修改的对象的一部分,而是在单独的数据结构中描述修改。
对于贫血模型,我希望呼叫者对事件负责。如果框架只是将DTO字段自动映射到任务,则可能不框架。您希望在代码中的某个点定义事件,以理解编辑的业务上下文。换句话说,您可能需要TaskRescheduled
而不是TaskUpdated
。
在初稿中,您可以在知道保存成功时发布事件。
更强大的是使用任务保存事件列表。这为您提供了关于可靠消息传递的更好故事 - 请参阅Udi Dahan Reliable Messaging Without Distributed Transactions以更好地了解这种情况。
如果域模型不足,您确实会在任务更新中定义事件(数据模型中的事件仍然会与任务的状态分开)。
答案 1 :(得分:0)
我更喜欢每次设置一个事件,因为有时更新操作只是一个用例,请想象一下,由于外部过程,您稍后将不得不在域中仅更改实体的一个字段,您应该有一个代表该用例的命令,而不是整个更新。
现在出现了一个问题:如何跟踪基于单个用例引发的事件?很简单,使用某种关联标识符,例如可以是请求ID。
要实现此目的,您可以使用包含域事件的列表,并在保存事务时调度事件,并且这些事件是在同一逻辑上下文中创建的,它们将具有相同的相关性ID。