【问题标题】:Can a DDD repository be stateful?DDD 存储库可以是有状态的吗?
【发布时间】:2017-12-15 20:05:13
【问题描述】:

我正在设计一个运输应用程序并尝试使用 Clean Architecture。我试图找出在哪里保存 Shipment 对象的状态,这样我就不必在每次用户单击 UI 中的按钮时重新实例化一个新对象。这是流程。

  1. 用户在 UI 中输入送货编号
  2. UI 控制器处理 UI 事件并实例化用例交互器的实例 一种。将存储库实例传递到用例交互器的构造函数中
  3. 用例交互器通过调用工厂(例如 CREATE_BY_DELIVERY)来实例化 Shipment 的实例。工厂调用 Repository 从数据库中收集数据。
  4. 在 UI 上填充交付数据
  5. 用户然后单击“报价单”按钮
  6. UI Controller 处理按钮点击事件并调用 Use Case Interactor 的 RATE_QUOTE 方法 一种。用例交互器是否需要像第 3 步一样再次调用 Shipment 工厂,或者用例交互器能否获取已在第 3 步中创建的 Shipment 对象的实例?
  7. 费率显示在 UI 上
  8. 用户然后单击处理发货按钮
  9. UI Controller 处理按钮点击事件并调用 Use Case Interactor 的 PROCESS_SHIPMENT 方法 一种。用例交互器是否需要像第 3 步一样再次调用 Shipment 工厂,或者用例交互器能否获取已在第 3 步中创建的 Shipment 对象的实例?

发货对象的状态应该是 UI 控制器、用例交互器还是存储库上的实例变量?理想情况下,我想将它保存在某个地方,这样我就不需要在每次用户单击 UI 上的按钮时都创建一个新对象。

提前谢谢你!

【问题讨论】:

    标签: domain-driven-design ddd-repositories clean-architecture hexagonal-architecture


    【解决方案1】:

    DDD 存储库可以是有状态的吗?

    是的,绝对是——这是原始描述中要点的一部分

    一个存储库将某种类型的所有对象表示为一个概念集(通常是模拟的)。它就像一个集合,除了具有更精细的查询能力......对于需要全局访问的每种类型的对象,创建一个可以提供该类型所有对象的内存集合的错觉的对象 em>。

    换句话说,重点是将应用程序组件与集合的实现细节分开。就应用程序而言,存储库可以实现为有状态的、内存中的键/值存储。

    理想情况下,我想将它保存在某个地方,这样我就不需要在每次用户单击 UI 上的按钮时都创建一个新对象。

    为了使您的代码易于理解,您应该可能每次只创建一个新对象,并且只有在您有明确的业务案例时才处理缓存的复杂性。

    也就是说,存储库的实现绝对没有理由不能包含最近使用对象的缓存。您只需要愿意投资于缓存失效策略即可。

    记住,Phil Karlton 多年前就教过我们

    计算机科学中只有两个难点:缓存失效和命名。

    【讨论】:

    • 同意。我将补充一点,您的 actual 存储库实现不应包含任何缓存。而是使用 装饰器模式 来包含缓存。这个装饰器将包装实际的实现(可能是构造函数注入),然后执行缓存。您的用例仍然需要IShipmentRepository,但您将实例化“包装器”并传递存储库实例。通过这种方式,您可以保持存储库的清洁。
    【解决方案2】:

    从理论上讲,它始终是有状态的。您是在询问存储库在加载/存储聚合时是否可以使用缓存。所以是的,但是。缓存是一件复杂的事情,除非必要,否则应该避免。

    在这种特殊情况下,使用缓存会损害应用程序的水平可伸缩性。很难有多个实例。在数据库/持久性级别很难使用乐观锁定,加载聚合时需要正确设置聚合的版本(它必须是最大的),否则预期的版本(加载的版本+1)不匹配。换句话说,正如@VoiceOfUnreason 所说,很难以有效的方式使缓存失效。

    因此,如果您愿意放弃水平可伸缩性,那么可以,您可以缓存聚合。

    附:这不适用于事件来源的聚合存储库。在这种情况下,您可以将快照保留在内存中,但仍然触摸/查询事件存储以获取新事件。

    【讨论】:

    • 感谢您提供的信息。将对象存储在用例交互器中甚至是一种选择吗?或者这会违反干净的架构原则吗?
    • @TonyRaimo 它不会违反任何规定。在这种情况下,Interactor` 的作用就像一个缓存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 2021-08-19
    相关资源
    最近更新 更多