背景
Udi Dahan建议使用fetching strategy作为数据访问的有用模式。我同意。
其概念是使角色显式。例如,我有一个聚合Root - Customer。我希望在我的应用程序的几个部分中有customer -一个可供选择的客户列表,一个客户详细信息的视图,我想要一个按钮来停用一个客户。
Udi似乎会为每个角色提供一个接口。因此,我有非常基本的细节的ICustomerInList,ICustomerDetail,包括最新购买的10种产品,以及IDeactivateCustomer,它有一种方法来停用客户。在每种情况下,每个接口公开的Customer Aggregate Root刚好足以完成工作。我的客户聚合根实现了所有这些接口。
现在,我想为每个角色实现一个抓取策略。每种策略都可以将不同数量的数据加载到我的Aggregate Root中,因为它将位于一个仅公开所需信息位的接口后面。
实现这一部分的一般方法是询问服务定位器或一些其他样式的依赖项注入。这段代码将获取您想要的接口,例如ICustomerInList,并找到一个获取策略来加载它(IStrategyForFetching<ICustomerInList>)。这个策略是由一个类实现的,该类知道只向客户加载ICustomerInList接口所需的一些信息。
到目前一切尚好。
问题
传递给服务定位器或IStrategyForFetching<ICustomerInList>的内容。我看到的所有例子都只是通过一个已知的id选择一个对象。这种情况很简单,调用代码传递此id并将返回特定的接口。
如果我想搜索呢?或者我想要客户列表的第二页?现在我想传递Fetching Strategy需要的更多术语。
可能的解决方案
我见过的一些示例使用谓词-如果特定的聚合根应该是结果集的一部分,则返回true或false的表达式。这在某些情况下工作得很好,但是如何才能取回前n个客户而不是更多呢?或者获取搜索结果的第二页?或者结果是如何排序的?
我的第一个反应是开始向我的IStrategyForFetching<ICustomerInList>添加泛型参数,它现在变成了IStrategyForFetching<TAggregateRoot, TStrategyForSelecting, TStrategyForOrdering>。这很快就会变得复杂和丑陋。由于不同的存储库,它变得更加复杂。一些存储库仅在使用特定策略进行选择时才提供数据,而有些存储库仅提供特定类型的排序。我希望能够灵活地实现通用存储库,这些存储库可以采用排序功能,以及只返回以特定方式排序的聚合根的专用存储库。
听起来我应该应用开始时使用的相同模式-如何使角色显式?我是否应该使用有效负载Y(搜索/排序参数)来实现获取X(聚合根)的策略?
编辑(2012-03-05)
如果我每次都不返回聚合根,那么这一切仍然有效。如果每个接口都是由不同的DTO实现的,我仍然可以使用IStrategyForFetching。这就是这个模式强大的原因--获取的内容和返回的内容不必以任何方式映射到聚合根。
我最终还是使用了IStrategyForFetching<TEntity, TSpecification>。TEntity是我想要得到的东西,TSpecification是我想要得到的东西。
发布于 2012-03-02 22:02:08
你遇到过CQRS吗?Udi是一种big proponent of it,它的目的就是为了解决这个问题。
其最基本形式的概念是将域模型与查询分离。这意味着只有当您想要执行命令/提交事务时,域模型才会起作用。您不使用聚合和实体中的数据来在屏幕上显示信息。相反,您需要创建一个单独的(或多个)数据访问服务,其中包含提供每个屏幕所需的确切数据的方法。这些方法可以接受criteria对象作为参数,因此可以使用您想要的任何条件进行搜索。
以下是它的工作原理的快速序列:
UI向命令服务(或DDD术语中的应用程序服务)发送一个包含customer.
使用CQRS架构构建您的应用程序为您提供了许多有关性能和可伸缩性的可能性。您可以进一步使用这个简单的示例,创建单独的查询数据库,其中包含每个视图、最终一致性和事件来源的非正规化表。有很多关于CQRS的视频/例子/博客,我认为你会真正感兴趣。
我知道你的问题是关于“抓取策略”的,但我注意到他在2007年写了这篇文章,很可能他认为CQRS是它的胜利者。
总结一下我的答案:
发布于 2012-03-03 10:13:39
为了增加David Masters的响应,我认为所有获取策略接口都增加了不必要的复杂性。让客户AR实现各种接口,这些接口是根据UI建模的,这对AR类来说是一个不必要的约束,您将花费大量的精力来执行它。此外,这是一个脆弱的解决方案。如果视图需要的数据虽然与Customer相关,但不属于customer类,该怎么办?然后,是否强制客户类和相应的ORM映射包含该数据?为什么不能有一组单独的类用于查询并完成它呢?这允许您在属于它们的地方处理获取策略-在存储库中。此外,获取策略接口抽象真正增加了什么价值?它可能是应用程序中正在发生的事情的适当模型,但它对实现它没有帮助。
https://stackoverflow.com/questions/9495832
复制相似问题