当前位置: 首页 > 知识库问答 >
问题:

域驱动设计中值或实体类型的存储库

柴磊
2023-03-14

我正在阅读领域驱动设计中的存储库和Microsoft微服务架构模式,他们都同意我应该为每个聚合根拥有一个存储库。我大体上同意这一点,但我有一个命名问题。

聚合是存储库作为...

实体是???

值是???

在我的特定场景中,我有一个营销网站上下文中产品对象的存储库。

Product是ProductInfo营销信息实体(Aggregate Root)、ProductSpec和ShippingInfo实体列表以及对其他有界上下文的RelatedProduct值引用的集合。

现在在我的存储库中,我必须从不同的实体和值对象中提取数据,以创建聚合根。

我从CMS获取产品信息(根)和相关产品(值)。ProductSpecs(entity) 和 ShippingInformation(entity) 来自 rest API(处理其他边界上下文的微服务)。

在我的第一次尝试中,我为所有实体创建了存储库/接口/域poco,然后让用户界面层将它们映射到视图模型以进行显示。本质上是为每个实体创建一个聚合,但是实体的形状像数据访问对象(因为在这一点上它们是),这些关注点正在泄漏到我的域中。如果当我们贬低运输应用编程接口并将其迁移到内容管理系统时,我将不得不删除并更新存储库/接口,然后去更新用户界面层中触及这些的所有内容,因为我改变了存储东西的位置。

我目前的尝试是使聚合更大一点,以更好地表示系统如何使用对象而不是存储方式,但我觉得我陷入了如何命名提供实体和值的类以及如何构建它。

我希望我的CMS和Api查询html" target="_blank">逻辑在单独的项目/dll中,以便它们可以重用,我想要一个结合数据访问对象来创建聚合的存储库。我怎么称呼CMS和Api查询项目中的类?我应该使用的模式有名字吗?

共有1个答案

羊刚捷
2023-03-14

领域驱动的设计概念都是关于领域模型的,它应该完全独立于使用的技术。您可以通过让域定义具有预期行为的业务驱动接口来实现这一点。然后,您的基础结构使用适当的技术实现这些接口。在搜索控制原理的反转时,您可以找到有关此策略的更多信息。

Eric Evans在他的《DDD》一书中的知识库模式是这种策略的一个很好的例子。我只能猜测他引入了存储库模式,而不是更通用的控制原则反转,因为这是使用技术持久化对象的最常见的情况。

对我来说,存储库也是一个非常重要的模型类型的工厂,聚合。因此,您应该按照从 Microsoft 获取的参考资料中所述使用它们。这包括您的存储库能够为您提供根聚合作为一个完整的一致单元,包括嵌入实体和值对象。

这是您的根聚合能够承担责任始终在其边界内管理一致状态的唯一方式。埃里克在这里谈到保持不变量。

到现在为止,一直都还不错。现在你来了一个丑陋的部分。如果您对聚合进行建模,使其最适合您的领域,则必须解决将域模型映射到特定数据库模型/技术的问题。这称为对象关系阻抗失配。JPA、Hibernate等对象关系映射器(ORM)应该为您解决这个问题,但问题仍然是这可能是一个麻烦而棘手的部分。

尽管如此,您应该在存储库实现中隐藏所有这些丑陋的东西。您将需要他们的DAO、JEE实体、实体管理器。管他呢。但是你永远不会在存储库接口之外公开它们。

最后,我将介绍您的 GUI 主题。谁将域及其所有细粒度模型元素一起使用?通常只有从用户输入制定命令并为用户输出提供视图的应用程序层。您可以将应用层视为 GUI 和域之间的转换器。出于这个原因,您可以向 GUI 公开某种缓慢变化且长期稳定的模型,并且可以在模型中快速更改。

希望这有帮助

 类似资料:
  • 刚开始使用域驱动设计,我了解到您应该将模型保持在有效状态,并且在创建类的新实例时,建议将所有必需的属性作为构造函数参数。 但是,当使用自动递增的键时,当我从持久层调用Add方法时,我只有这个新ID。如果我在没有密钥的情况下实例化对象,我认为它们将处于无效状态,因为它们需要某种唯一标识符。 我应该如何实现我的架构,以便在创建我的实体的新实例之前拥有我的id?

  • 我正在学习DDD概念,为了加强我的理解,我正在研究一些现实世界的例子。 我知道一个聚合应该只有一个通过根实体的入口点,一个聚合应该只有一个存储库(如果我完全理解错了,请纠正我) 现在假设有特定类型的消耗品,并且这些消耗品是从配送中心发送的。发送特定类型的消耗品取决于它们的数量,我的意思是,如果其中一个消费者对A型和B型的临界数量为10,并且这些项目的数量低于10,那么配送中心发送A型和B型消耗品。

  • 我正试图让我的头绕过DDD,但我卡住了。这就是我如何设置我的项目: 然后,我继续实现UserRepository,这里我遇到了另一个问题:UserRepository接口需要域用户模型,当我试图在DAL中实现接口时,我需要使用域用户模型来实现它,这导致DAO是为域模型而不是DAL模型创建的,这没有任何意义。唯一能修正的就是在域层中引用DAL,这是错误的。 有人能解释一下我在DDD中遗漏了什么吗?

  • DDD指定每个聚合的存储库,但当采用Spring数据JPA时,我们只有在声明每个实体的接口时才能利用这些好处。如何解决阻抗失配问题? 我希望尝试封装在聚合存储库中的存储库接口,这是一个好的解决方案还是更好的解决方案? 举个例子:是聚合根,实体如、、等,每个实体都可以从拥有自己的存储库接口中受益。什么是不违反DDD的最佳方式?

  • 以前,我会将存储库注入到服务层。所以我的问题是--可以将存储库注入域对象,以便它们能够执行业务规则吗?

  • null 到目前为止,很容易。如果我们试图将规范应用到存储库,而又不破坏DDD模式或存在性能问题,那么问题就会出现。 应用规范的可能方法: 1)经典方法:在领域层使用领域模型进行规范 null null 3)与2)类似,但将规范作为持久层的一部分 这不起作用,因为域层需要参考规范。它仍将取决于持久层。 我们将在持久层中拥有业务逻辑。这也违反了DDD模式 4)与3类似,但使用抽象规范作为接口 nul