DDD:如何处理大型集合

时间:2014-09-18 14:27:42

标签: domain-driven-design ddd-repositories

我目前正在为REST中的社交网络相关应用程序设计后端。我对DDD原则非常感兴趣。现在我们假设我有一个User对象,其中有一个Friends of Friends。如果应用程序和用户变得非常成功,这些可能是数千。每个朋友都会有一些属性,它基本上是一个用户。 查看DDD Cargo application example,可以不时地从CargoRepository存储和检索完全展开的Cargo对象。哇,如果聚合根中有一个列表,随着时间的推移,这将最终触发OOM。这就是为什么如果从数据中心的角度来看待问题,就会出现分页和延迟加载的原因。但是你怎么能在持久性 - 不知道的DDD中处理这些大型集合呢?

4 个答案:

答案 0 :(得分:3)

正如@JefClaes在评论中提到的:您需要确定您的User AR是否确实需要Friends的集合。

所有权并不一定意味着必须收藏。

采用Order / OrderLine示例。如果 OrderLine的一部分,则Order没有任何意义。但是,Customer所属的Order没有Orders的集合。如果客户被限制为最大数量(或金额),则可能有ActiveOrders的集合。保留一系列历史订单是不必要的。

我怀疑大型收集问题不仅限于DDD。如果一个人收到一个有数千行的Order,可能会有设计权衡,但订单可能更容易被分成更小的订单。

在你的情况下,我会断言Friend的包含/排除与User AR的一致性几乎没有关系。

要记住的是,只要您开始使用域模型来查询您的开始遇到奇怪的问题。因此,总是尝试用一些简单的查询接口来考虑一些读/查询模型,该接口可以直接访问您的数据,而无需使用您的域模型。这可能会简化事情。

因此,Relationship AR可能会在这方面提供帮助。

答案 1 :(得分:1)

如果某些分页或优化技术是您网域的一部分,那么使用此功能设计域类并没有错。

我想过的一些解决方案

  1. 如果用户是聚合根,则可以使用封装特定用户对象构造的方法UserRepository填充GetUserWithFriends(int userId, int firstFriendNo, int lastFriendNo)。同样,您也可以使用某些计数器等填充用户模型。
  2. 另一方面,可以为User实例_friends字段实现延迟加载。因此,User实例本身可以决定哪个" part"朋友列表加载。
  3. 最后,您可以使用UserRepository获取某些用户的所有朋友的分页或其他过滤条件。它并没有违反任何DDD原则。
  4. DDD太大了,不能说它不适合CRUD。以DDD方式编程时,您应始终考虑一些技术限制并调整您的域以满足它们。

答案 2 :(得分:0)

不要过早优化。如果你害怕承受很大的压力,那么你必须对你的应用程序进行基准测试并进行压力测试。

你需要有一个这样的表:

friends
id, user_id1, user_id2

处理n-m关系。在那里索引你的字段。

另外,你需要知道朋友是否对称。如果是这样,那么如果他们是朋友,那么你需要为两个人提供一行。如果没有,那么您可能有一行,表明用户是与另一个用户的朋友。如果另一个人也认为第一个朋友也是,那么你需要另一行。

可以通过隐藏(AJAX)请求实现延迟加载,这样用户就会觉得它比实际更快。但是,我现在不担心这些问题,因为稍后您可以将表的内容迁移到现在由于项目无限可能演变而未知的新结构。

答案 3 :(得分:0)

您的聚合根可以包含不同对象的集合,这些对象仅包含一小部分信息,作为对实际业务对象的引用。然后,在需要时,可以使用项目从底层存储库中获取全部信息。