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

时间:2017-12-15 20:05:13

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

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

  1. 用户在UI中输入交货编号
  2. UI Controller处理UI事件并实例化Use Case Interactor的实例   一个。传递给用例交互器
  3. 的构造函数的存储库实例
  4. Use Case交互器通过调用Factory来实例化Shipment实例(例如CREATE_BY_DELIVERY)。工厂调用存储库以从数据库中收集数据。
  5. 在UI上填充交付数据
  6. 用户然后点击“报价单”按钮
  7. UI Controller处理按钮单击事件并调用Use Case Interactor的RATE_QUOTE方法 一个。 Use Case Interactor是否需要在步骤#3中再次调用Shipment工厂,或者Use Case Interactor是否可以获取已在步骤3中创建的Shipment对象的实例?
  8. 费率显示在用户界面
  9. 用户然后单击PROCESS出货按钮
  10. UI Controller处理按钮单击事件并调用Use Case Interactor的PROCESS_SHIPMENT方法 一个。 Use Case Interactor是否需要在步骤#3中再次调用Shipment工厂,或者Use Case Interactor是否可以获取已在步骤3中创建的Shipment对象的实例?
  11. 出货对象的状态应该是UI控制器,用例交互器还是存储库中的实例变量?理想情况下,我想将其保存在某个地方,因此每次用户点击用户界面上的按钮时,我都不需要继续创建新对象。

    提前谢谢!

2 个答案:

答案 0 :(得分:3)

  

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

是的,绝对 - 这是原始描述中的一部分

  

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

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

  

理想情况下,我想将其保存在某个地方,因此每次用户点击用户界面上的按钮时,我都不需要继续创建新对象。

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

尽管如此,绝对没有理由认为存储库的实现不能包含最近使用的对象的缓存。您只需要愿意投资缓存失效策略。

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

  

计算机科学中只有两件事:缓存失效和命名事物。

答案 1 :(得分:2)

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

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

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

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