将存储库注入域对象或存储库应该了解业务逻辑?

Injecting repositories to domain objects or repositories should be aware of business logic?

假设我们有一个 class Order(与用户相关)并且它有 属性 state。我想防止同时有多个确认订单,所以在我确认任何订单之前,我必须检查在它的时间段内是否已经有一些确认。

我可以采用两种方法(我知道):

  1. OrderRepository 有一个函数 changeState 可以在更改之前搜索冲突的已确认订单,并且只有在没有找到任何东西时才允许它 - 这里的问题是存储库知道逻辑改变状态。

  2. OrderRespository 被注入 Order 并且 Order 具有函数 changeState 将使用该存储库检查冲突 - 这里的问题是域对象了解持久性。

什么是正确的做法?

考虑这个问题的另一种方法是从存储库责任的角度来看。归根结底,存储库是一种抽象,表示如何处理对象集合,在您的例子中是订单。

因此,为要在存储库层表示的集合保持一致性和正确状态的规则是有意义的。将存储库注入实体可能是一种代码味道,表明某些东西没有被正确建模。我会选择你的第一个版本,但也许你不需要具体说明你的状态变化,而只需将这些规则嵌入到 save() 方法中。如果没有其他人同时确认,您可以保存对订单的更改。

存储库不负责域不变量。聚合是。如果聚合内部没有所需的信息来检查不变量,请尝试质疑您的聚合设计并可能提出一个新的设计。

您也可以使用域服务。作为一个较弱的选择,您还可以将域不变量降级为简单的用例前提条件,并让应用程序 Service/Command 处理程序对其进行检查。请注意,后两个选项不能提供强有力的保证,即域实体将始终处于与该规则一致的状态。