实施领域驱动设计和交易

Implementing Domain-Driven Design and Transactions

在阅读 Vaughn Vernon 的实施领域驱动设计后,我至少对一件事感到困惑。 在第 12 章存储库中,他说事务是在应用程序层中管理的。 但他也说聚合是事务一致性边界的同义词。 由于存储库提供了对聚合的全局访问,为什么不能管理事务 在存储库中?是因为规则 aggregate == transactional consistency boundary 只是一个经验法则 有时必须打破,还是有其他问题?

新答案

很高兴能想起我多年前写的奇怪的东西...

那么,今天我将如何回答这个问题:

确实,聚合边界是一致性边界。这个定义不仅意味着它是技术事务的边界,而且意味着聚合必须确保在其上执行的操作不会使聚合本身进入无效状态。这些不变量很少是技术性的,但通常是面向业务的。

说到持久性,这正是接受的答案中提到的。存储库负责持久性。有大量的存储库实现在物理上无法确保从头到尾的交易。此外,某些情况可能涉及特定于应用程序的问题,例如能够处理乐观并发等。这不是存储库可以做的事情。在物理上,存储库会在执行操作之前注意从某种持久性中检索聚合状态,并在操作完成时将状态突变持久化。

因此,命令处理的事务成为应用程序关注点,而不是持久性关注点。

旧答案

通常,存储库会在构造函数中注入一些 SessionUnitOfWork 来实例化,以获得持久存储连接。在一个应用程序服务调用中共享相同的连接是有益的,并且通常这样的调用本身是事务性的,包括读取和写入。我希望这能解释基本原则。 Vernon 给出了 @Transactional 注释应用程序服务方法的示例。

此外,在第 367 页上,您可以找到一个名为 违反规则的原因 的部分,他在其中解释了为什么您有理由在一个事务中更新多个聚合。

我的最后一点是,您应该记住,集合式存储库不太了解内容如何提交到存储。他们跟踪更改并向 UoW 报告,后者执行提交(或回滚)。

why couldn't transactions be managed in repositories?

因为存储库不是 "a business transaction" 的抽象,存储库是 "a collection of domain objects that you can take from or add to" 的抽象。

根据定义,交易有开始和结束。这是一个过程。存储库不是。 Transaction和Repository的关系不是is-a,而是has-a。事务使用其存储库。

当我们说聚合应该是一致性边界时,我们的意思是它应该是唯一的状态块交易所包含,而不是聚合应该是 交易相同。

事务在应用层的原因之一是 ApplicationService 的执行通常会改变一个 Aggregate 而这个 Aggregate发布 DomainEvents 必须与 Aggregates 一起存储在同一个事务中。