代码之家  ›  专栏  ›  技术社区  ›  David Masters

DDD-如何实现搜索的高性能存储库

  •  25
  • David Masters  · 技术社区  · 14 年前

    我有一个关于DDD和存储库模式的问题。

    假设我有一个客户集合根目录的客户存储库。get&find方法返回完全填充的聚合,其中包括地址等对象,一切正常。但是当用户在用户界面中搜索客户时,我只需要一个聚合的“摘要”——只是一个带有摘要信息的平面对象。

    我可以处理这一问题的一种方法是正常调用存储库上的find方法,然后在应用程序层中,将每个客户聚合映射到customersearchresult/customerinfo dto,并将其发送回客户机。

    但我对此的问题是性能;每个客户聚合可能需要多个查询来填充所有关联。因此,如果我的搜索条件匹配了50个客户,那么对于可能检索我甚至不需要的数据的数据库来说,这是一个很大的打击。

    另一个问题是,我可能希望包括有关客户的汇总数据,这些数据超出了客户的汇总根边界,例如最后一个订单的日期。订单有它自己的聚合,因此为了获得客户的订单信息,我不得不调用orderrepository,这也降低了性能。

    所以现在我想我有两个选择:

    1. 向customerrepository添加一个额外的find方法,该方法通过执行一个有效的查询返回这些摘要对象的列表。

    2. 创建一个专门构建的readonly customerforepositional,它只有1中描述的find方法。

    但这两个都让我觉得我违背了DDD的原则。我的存储库继承自一个通用库:存储库,其中t:iagregateroot。这些摘要信息对象不是聚合,与T的类型不同,因此1确实与设计背道而驰。

    也许对于2,我会创建一个没有IAGregateroot约束的抽象搜索存储库?

    在我的领域中有许多类似的场景。

    您将如何实现这个场景?

    谢谢, 戴夫

    更新

    在阅读了Theo的答案之后,我认为我将使用选项2,在我的基础架构中创建一个专门针对这些场景的搜索库。然后,应用层(WCF服务)可以调用这些存储库,这些存储库只是直接填充摘要DTO,而不是将域实体映射到DTO。

    ****更新2***

    虽然一年前我问过这个问题,但我想补充一下,我已经发现了旨在解决这个确切问题的CQR。Udi Dahan http://www.udidahan.com/ )还有格雷格·杨( http://codebetter.com/gregyoung/ )写了很多关于它的文章。如果您正在使用DDD创建分布式应用程序,那么CQR就是为您准备的!

    2 回复  |  直到 8 年前
        1
  •  25
  •   Theo Lenndorff    8 年前

    我认为您只想显示摘要信息。这些汇总信息位不是域模型的实体或值对象。它们只是信息而已。

    它类似于显示报告信息。如果我处理这些事情,我不会坚持纯DDD方法。你建议的选择是可以的,因为它可以完成你的工作。DDD不应被视为教条。跳出框框思考。放松一点DDD。

    但请注意,您只是在模型外部创建信息值,以显示目的。因此,如果用户选择一位信息对其进行某些操作(在域模型中定义),则需要从信息值中提取标识符,并从存储库中提取实体/值对象/聚合。

    我强烈推荐此视频: Eric Evans: What I've learned about DDD since the book . 如果你读他的书,你真的应该看整个视频。在30:00左右,埃里克·埃文斯自己谈论聚合并提到你目前遇到的问题时,要密切关注。

        2
  •  1
  •   Jamie Ide    14 年前

    我会:

    1. 返回表示要显示的对象视图的其他对象,例如customerinfo。
    2. 返回数据表。通常,通用容器是最简单和最好的方法。

    如果您的通用基础知识库中的T是客户,那么我认为您错误地应用了聚合根的概念,尽管我不是严格的 Evansangelist . 我将为客户设计一个存储库,该存储库返回逻辑上或舒适地与客户分组的任何数据,包括作为客户数据视图的数据表或只读对象。