【问题标题】:Why shouldn't a repository hold transaction logic?为什么存储库不应该保存事务逻辑?
【发布时间】:2013-12-19 17:33:17
【问题描述】:

拥有一个设计良好的域,具有不相互引用的聚合、明确定义的边界和具有明确定义的对象引用的聚合对象,为什么在存储库中包含事务逻辑是一种不好的做法(为每个域创建一个存储库目的)?

在用 UoW 模式回答之前,请考虑这个问题UoW limitation

【问题讨论】:

  • 您能否发布一个示例,说明“在存储库中具有事务逻辑”的含义?存储库中的给定方法是否包含整个业务事务,您是否会调用存储库上的单独方法来启动和提交事务...?

标签: design-patterns architecture transactions domain-driven-design


【解决方案1】:

因为典型的事务通常跨越多个存储库。当您在同一笔交易中出售您想要的产品时,

  • 减少库存中的元素数量 (StockRepository)
  • 创建订单 (OrderRepository)
  • 创建货件 (ShipmentRepository)

你真的希望所有这些要么成功要么失败。

【讨论】:

  • 存储库不能像域中的对象一样保存对其他存储库的引用吗?那么事务可以驻留在这一层吗?如果不是,事务逻辑应该驻留在哪里? UoW 限制我进行简单交易,例如链接的问题。我应该为了这些交易的目的而创建一个服务层吗?
  • 为了交易的目的,实现你的业务逻辑。当您销售 10 件产品时,您想创建一个包含 10 个订单行的订单,并根据产品的重量和数量尽可能多地发货,并在新库存量低于某个限制时发出警报等. 那是需要实现的业务逻辑,不属于所涉及的三个存储库中的任何一个。存储库的全部意义在于将持久性逻辑与业务逻辑分离。
  • 我有点不同意。如果您有一个干净的域模型并遵循“每个事务一个聚合根”原则,即通过将跨越多个聚合的所有业务逻辑移动到一个长期运行的流程/传奇中,我看不出您的存储库应该有任何理由t 处理事务逻辑。恰恰相反,事务逻辑是一个与数据库概念高度紧密的基础设施问题,而其他存储方法,例如文件系统,则没有事务的概念。
  • @JBNizet 您永远不会有 OrderLineRepository,因为订单行是 Order 的详细信息,因此您只有 OrderRepository。 Alexander Langer 有一点,对于跨越多个域/服务器的事务,saga 是实现它的最干净的方法,存储库不应该知道它。如果一个域存储库将内容存储在云中或文件系统中怎么办? ACID 适用于某些数据库引擎,它是一种特殊情况解决方案,而不是通用解决方案。如今,高效的查询大多是 nosql 域。 RDBMS 仍然有作用,但它不再具有垄断地位。
  • 如果某个逻辑需要调用多个repository,那么这个逻辑应该在一个service中。我不明白为什么用他们的产品检索订单需要的不仅仅是一个查询。如果需要,我将创建一个服务,该服务将调用订单存储库中的适当方法,以及产品存储库中的适当方法。否则,您很快就会得到意大利面条式的依赖,您还会在产品存储库中引用订单存储库,从而导致循环依赖。
【解决方案2】:

即使在每个事务一个聚合的情况下,代码块通常看起来像这样:

 Order order = orderRepository.findBy(orderId);(1)
 order.doSomething();
 orderRepository.store(order);//or omitted with uow

从技术上讲,当某些步骤在存储库之外时,如何在存储库内实现事务逻辑和锁定策略?

【讨论】:

    【解决方案3】:

    因为它违反了单一职责原则。存储库是聚合根集合的提供者,而不是事务协调器。此外,它们的实现驻留在 Persistence 层,这意味着它们的视野太低级,甚至无法意识到业务事务等全局问题。

    【讨论】:

    • :) 你如何持久化你的对象?实际上,它们还需要数据库层的一致性。他们的视野不是那么低,你还需要在数据库中映射状态,这样你就可以检索到consitent对象。我专门指的是数据库事务(也需要一致性)。出于一致性原因,您甚至可以在数据库端为复杂的设计/逻辑进行触发器(我不得不这样做以实现数据库多态关联)。这个例子只是为了表明数据库也需要与域相关的一致性。
    • 我不通过存储库保存我的对象。我从存储库公开的集合中添加或删除对象,或修改它们,但这些更改不会立即保留。一个应用层服务,它知道正在进行的用例的状态,可以决定何时持久化。 如何 持久化也不是由您的存储库实现的,而是通常由您的 ORM 实现的。即使没有 ORM,我也会有一个特定的适配器对象,它可以从逻辑/业务提交转换为物理提交(可以是数据库事务提交或其他东西)。分开的职责,分开的对象。
    • 我认为您将工厂与存储库混淆了。存储库是从存储技术中抽象出模型的层。即使您使用 ORM ,您也应该从存储库中调用映射器(谁知道以后您可能会切换到非关系数据库)。
    • 工厂与此无关。我并没有说存储库不应该调用 ORM,只是说它不应该知道如何持久化(= 对持久化存储进行最终提交)。有一个我的意思的例子:richarddingwall.name/2009/10/22/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 2021-03-24
    相关资源
    最近更新 更多