Design patterns 规范模式与DDD

Design patterns 规范模式与DDD,design-patterns,nosql,repository,domain-driven-design,polyglot-persistance,Design Patterns,Nosql,Repository,Domain Driven Design,Polyglot Persistance,在学习更多DDD模式的个人游戏项目中,我缺少一个过滤器对象 环顾四周寻找示例,似乎所有东西(如LinQ)都面向SQL数据库。然而,对于许多NoSQL数据库,大多数查询,即使只是“select*from table”也需要预定义的视图。然而,如果存储库映射一个web服务,即使查询的类型也要严格得多 考虑到非SQL数据库的限制,规范模式是否有变化?我觉得这需要使用继承和静态声明来支持不同类型的持久性后端 我应该如何在我的存储库中结合“排序”和“筛选”?作为一个例子,考虑“强”> 强>项列表的存储库。

在学习更多DDD模式的个人游戏项目中,我缺少一个过滤器对象

环顾四周寻找示例,似乎所有东西(如LinQ)都面向SQL数据库。然而,对于许多NoSQL数据库,大多数查询,即使只是“select*from table”也需要预定义的视图。然而,如果存储库映射一个web服务,即使查询的类型也要严格得多

考虑到非SQL数据库的限制,规范模式是否有变化?我觉得这需要使用继承和静态声明来支持不同类型的持久性后端

我应该如何在我的存储库中结合“排序”和“筛选”?作为一个例子,考虑“强”> <>强>项列表的存储库。

(Query)findAllSortedByDate;
(Query)findAllSortedByName;
(Query)findAllSortedByQuantity;
因此,当由表显示时,这些是不同类型的排序。因为我可能会处理大量结果,所以我从未考虑在视图或视图模型中进行排序或过滤。起初,我想到了一个Proyection类,它根据用户操作从存储库中选择正确的查询。但是,如果我想将不同的排序策略与不同的过滤器结合起来,那么这种方法就不能很好地工作

显然,我需要某种类型的“规范”对象,但我不确定是否:

  • 我应该将它们用于我的存储库,使它们更智能吗?或者我应该在视图模型中使用它们
  • 如何正确地限制我的规范对象以获得良好的多语言持久性
  • 最初,我考虑使用存储库作为查询接口执行任何查询,但现在我注意到视图模型也可以作为“有状态”类集合接口,而前者是“无状态”类集合接口

  • 总的来说,我应该尝试在我的存储库中保留任何类型的排序/筛选吗?如果所有查询结果都可以加载到内存中,那么这样做可能会增加不必要的复杂性
  • 更新
    要想提高这个问题,还可以考虑,虽然NoSQL的视图可以被过滤和排序,但是全文搜索可能需要一个外部索引引擎,如Lucene或SQLite FTS,它只提供实体的唯一身份,以便查询必须再次排序和过滤。

    < P> <强>过滤> <强> < /P> Fowler所说的“类似集合的接口”并不是指公开类似于数组或列表的API的东西:例如,它与此无关!存储库应该包含持久性层的所有技术细节,但其API应该定义为在业务领域中具有表现力

    您应该将规范视为与域相关的逻辑谓词(事实上,它们是域模型中的一级公民),可以组合成检查实体的不同质量,以及从集合中选择实体(可以是存储库或简单列表的集合)。例如,在我为一家意大利银行设计的金融领域模型中,我有
    债券规范持续时间
    标准和较差的长期评级规范
    等等

    实际上,在DDD中,规范来自业务需求(通常是合同界限),软件在运行期间必须强制执行这些需求。它们可以被用作过滤器的抽象,但这更像是一个幸运的副作用

    在排序时

    大多数情况下,排序(以及切片和分组…)只是一个表示问题。当它是一个业务问题时,应该从领域专家的知识中提炼出适当的比较器(以及分组等)作为领域概念。 然而,即使只是一个表示问题,在存储库中处理它也要高效得多

    在.NET上,解决这些问题的一个可能的(也是非常昂贵的)解决方案是编写一个自定义LINQ提供程序(或多个),它可以将所有可以用通用语言表示的查询翻译到所需的持久层。然而,这种解决方案有一个主要的缺点,如果您不能从一开始就翻译所有的查询,您将永远无法估计使用域更改应用程序的工作量:到时候您将不得不深入重构QueryProvider以处理新的复杂查询(而这样的重构会让你付出比你能承受的多得多的代价)

    为了解决这个问题,在(正在进行的工作和非常雄心勃勃的)框架(免责声明:我是核心开发人员)中,我们选择加入规范模式和查询对象模式,提供一个通用API,使客户端能够使用规范进行筛选、使用比较器进行排序和使用整数进行切片,而无需(不可预测的)LINQ的成本

    在Fowler方案(如下)中,我们将规范(aCriteria)和辅助排序要求传递给存储库:

    作为替代方案,您可以使用:如果您没有数千种不同类型的查询,那么这是一种更便宜的方法

    奖金解决方案

    一个快速但仍然正确的解决方案是“只”像查询一样使用持久性语言。DDD用于复杂的操作边界和查询(大多数情况下)不可操作:因此,您可以简单地使用SQL或NoSQL数据库提供的语言来检索所需的投影和/或所需操作的实体。您将看到您查询的数据集与确保域不变量所需的数据集有多么大的不同

    这就是为什么,例如,有时,序列化文件可能是解决当前问题的域持久性的最佳方法。
    毕竟,什么是fi
    findAll(Specification<Order> specification, 
            SortingOptions<Order> sortingOptions)