在阅读Eric Evans的DDD之后,我试图将其应用于我管理的项目。有一些特定于用户的查询数据,我不确定如何以DDD方式实现。
例如,如果用户查询通知,则应用程序应告知用户是否阅读了每个帖子。通常在这种情况下,我将使用如下数据进行响应:
{
"notices": [
{"content": "foo", "is_read": true},
{"content": "bar", "is_read": false}
]
}
假设有一个Notice
实体和Read
实体保存了一个User
读过的实体。还要假设有太多的用户在阅读该通知,即为is_read
检索所有用户并不是一种有效的方法。
由于没有Read
实体就永远不会查询Notice
实体,因此我可以将其放入Notice
聚合中。然后实现以请求用户为参数的查询功能。
或者我可以分离NoticeRepository
和ReadRepository
,查询通知,然后将它们与应用程序层结合在一起,并使用通知ID查询读取。
第一个选项似乎是假设用户查询通知并使用应用程序逻辑破坏域层。另一方面,第二个选项使我感觉到我正在以不必要的复杂方式实现简单功能。我现在真的无法想到其他选择。.在这种情况下,最佳实践是什么?
答案 0 :(得分:1)
我现在真的无法想到其他选择
我看到了两个可能使您绊倒的问题。
首先,您的域模型可能缺少一个重要概念。我们如何知道鲍勃是否阅读了特定的通知?域中可能有一些实体,可能是Acknowledgement
,捕获了Bob和他阅读的文档,以及该域可能感兴趣的其他信息(他阅读了哪个版本的文档?何时?通过什么渠道?何时?等等)。
因此,将产生的视图看起来像与Bob的确认一起加入的活动通知列表。
让您烦恼的另一件事是,尝试使用存储库来获取数据的“手工”连接确实是一个障碍。此外,自从编写蓝皮书以来,人们已经意识到了什么,这可能不是必需的。由于查询是safe,因此它们不会更改基础数据-并且如果基础数据不会更改,我们真的不需要域模型来保护业务不变量。
答案 1 :(得分:0)
这需要全部放在查询服务中,
埃里克·埃文斯(Eric Evans)的书是一个很好的基础,并且现在已经演变为更现代的模式,例如沃恩·弗农(Vaughn Vernon)的《实现域驱动设计(IDDD)》中的CQRS。
您的查询服务将负责显示通知列表,并在单独的表中为此用户更新读取列。
您可以在此处查看一些查询服务示例(用Java编写):
答案 2 :(得分:0)
我没有Read实体。只是通知和用户。在“用户”中,您将具有该用户已阅读的通知ID的列表(反之亦然,在“通知”中,您将具有已阅读该通知的用户ID的列表)。
然后,要查询需要在用户界面中显示的信息,您有几种选择,如Vaughn Vernon在他的《实现DDD》(第512页)中所述:
DTO
介体
域有效负载对象
状态表示形式
用例最佳存储库查询(与CQRS相似)
数据转换器