gpt4 book ai didi

design-patterns - 规范模式和 DDD

转载 作者:行者123 更新时间:2023-12-04 23:54:58 25 4
gpt4 key购买 nike

在一个学习更多关于 DDD 模式的个人游戏项目的上下文中,我缺少一个 Specification我的过滤器的对象。

环顾四周,似乎一切(如 LinQ)都面向 SQL 数据库。然而,对于许多 NoSQL 数据库,大多数查询,即使只是“从表中选择 *”也需要预定义的 View 。然而,如果存储库正在映射 Web 服务,那么查询的类型也会更加严格。

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

我应该如何在我的存储库中结合“排序”和“过滤”?例如,考虑 列表的存储库。订购 项目。

(Query)findAllSortedByDate;
(Query)findAllSortedByName;
(Query)findAllSortedByQuantity;

因此,当由表格显示时,这些是不同类型的排序。由于我可能会处理大量结果,因此我从未考虑在 View 或 View 模型中进行排序或过滤。最初我想的是 项目根据用户操作从存储库中选择正确查询的类。但是,如果我想沿不同的过滤器组合不同的排序策略,这将无法正常工作。

显然我需要某种类型的“规范”对象,但我不确定是否:
  • 我应该将它们用于我的存储库,使它们更智能吗?或者我应该将它们用于我的 View 模型?
  • 如何正确限制我的规范对象以获得良好的多语言持久性?

  • 最初我考虑使用 执行任何查询存储库作为 collection-like interface但现在我注意到 查看模型 也可以表现为“有状态”的类集合接口(interface),而前者是“无状态”的类集合接口(interface)。
  • 总的来说,我应该尝试在我的存储库中保留任何类型的排序/过滤吗?如果所有查询结果都可以加载到内存中,这样做似乎会增加不必要的复杂性。

  • 更新 :
    为了给这个问题增添趣味,还要考虑虽然 NoSQL View 可以过滤和排序,但全文搜索可能需要外部索引引擎,例如 Lucene 或 SQLite-FTS,只为必须排序的查询提供实体的唯一标识并再次过滤。

    最佳答案

    在过滤

    Fowler 所说的“类集合接口(interface)”并不是指暴露类似数组或列表的 API:它与 ICollection<T> 无关。 , 例如!存储库应该 encapsulate持久层的所有技术细节,但应该定义它的 API,以便它在业务领域中具有表现力。

    您应该将规范视为与域相关的逻辑谓词(实际上它们是域模型中的一等公民),可以由 组成。检查实体的不同品质从集合中选择实体 (可以是存储库或简单列表的集合)。例如,在我为一家意大利银行设计的金融领域模型中,我有 DurationOfMBondSpecification , StandardAndPoorsLongTermRatingSpecification等等。

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

    在排序

    大多数时候排序(以及切片和分组......)只是一个演示问题。当它是一个业务问题时,正确的 比较器 (以及石斑鱼等)应该从领域专家的知识中提炼为领域概念。
    然而,即使它只是一个演示问题,在存储库中处理它的效率要高得多。

    在 .NET 上,解决这些问题的一种可能(并且非常昂贵)的方法是编写一个自定义 LINQ 提供程序(或多个),它可以翻译 全部 可以用通用语言表达的查询到所需的持久层。但是,如果您无法翻译 ,此解决方案有一个主要缺点。全部 从一开始的查询,您将永远无法估计使用域更改应用程序的工作量:您将不得不深度重构 QueryProvider 以处理新的复杂查询(并且这种重构将花费你比你负担得起的要多得多)。

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

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

    enter image description here

    作为替代方案,您可以使用 custom repositories :如果您没有数千种不同类型的查询,这是迄今为止更便宜的方法。

    奖金解决方案

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

    这就是为什么,例如,有时,序列化文件可能是解决手头问题的域持久性的最佳方法。
    毕竟,什么是文件系统,如果不是最广泛的 NoSQL 数据库 ! :-D

    关于design-patterns - 规范模式和 DDD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18185704/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com