域驱动设计,如何处理用户特定的数据?

时间:2018-10-08 15:08:56

标签: domain-driven-design

在阅读Eric Evans的DDD之后,我试图将其应用于我管理的项目。有一些特定于用户的查询数据,我不确定如何以DDD方式实现。

例如,如果用户查询通知,则应用程序应告知用户是否阅读了每个帖子。通常在这种情况下,我将使用如下数据进行响应:

{
    "notices": [
        {"content": "foo", "is_read": true}, 
        {"content": "bar", "is_read": false}
    ]
}

假设有一个Notice实体和Read实体保存了一个User读过的实体。还要假设有太多的用户在阅读该通知,即为is_read检索所有用户并不是一种有效的方法。

  • 由于没有Read实体就永远不会查询Notice实体,因此我可以将其放入Notice聚合中。然后实现以请求用户为参数的查询功能。

  • 或者我可以分离NoticeRepositoryReadRepository,查询通知,然后将它们与应用程序层结合在一起,并使用通知ID查询读取。

第一个选项似乎是假设用户查询通知并使用应用程序逻辑破坏域层。另一方面,第二个选项使我感觉到我正在以不必要的复杂方式实现简单功能。我现在真的无法想到其他选择。.在这种情况下,最佳实践是什么?

3 个答案:

答案 0 :(得分:1)

  

我现在真的无法想到其他选择

我看到了两个可能使您绊倒的问题。

首先,您的域模型可能缺少一个重要概念。我们如何知道鲍勃是否阅读了特定的通知?域中可能有一些实体,可能是Acknowledgement,捕获了Bob和他阅读的文档,以及该域可能感兴趣的其他信息(他阅读了哪个版本的文档?何时?通过什么渠道?何时?等等)。

因此,将产生的视图看起来像与Bob的确认一起加入的活动通知列表。

让您烦恼的另一件事是,尝试使用存储库来获取数据的“手工”连接确实是一个障碍。此外,自从编写蓝皮书以来,人们已经意识到了什么,这可能不是必需的。由于查询是safe,因此它们不会更改基础数据-并且如果基础数据不会更改,我们真的不需要域模型来保护业务不变量。

答案 1 :(得分:0)

这需要全部放在查询服务中,

埃里克·埃文斯(Eric Evans)的书是一个很好的基础,并且现在已经演变为更现代的模式,例如沃恩·弗农(Vaughn Vernon)的《实现域驱动设计(IDDD)》中的CQRS。

您的查询服务将负责显示通知列表,并在单独的表中为此用户更新读取列。

您可以在此处查看一些查询服务示例(用Java编写):

https://github.com/VaughnVernon/IDDD_Samples/blob/master/iddd_collaboration/src/main/java/com/saasovation/collaboration/application/forum/ForumQueryService.java

https://github.com/VaughnVernon/IDDD_Samples/blob/master/iddd_collaboration/src/main/java/com/saasovation/collaboration/application/forum/DiscussionQueryService.java

答案 2 :(得分:0)

我没有Read实体。只是通知和用户。在“用户”中,您将具有该用户已阅读的通知ID的列表(反之亦然,在“通知”中,您将具有已阅读该通知的用户ID的列表)。

然后,要查询需要在用户界面中显示的信息,您有几种选择,如Vaughn Vernon在他的《实现DDD》(第512页)中所述:

  • DTO

  • 介体

  • 域有效负载对象

  • 状态表示形式

  • 用例最佳存储库查询(与CQRS相似)

  • 数据转换器