Java 在域驱动设计中,为什么要使用“;合计”;对象以及在设计聚合时应用哪些关键原则?

Java 在域驱动设计中,为什么要使用“;合计”;对象以及在设计聚合时应用哪些关键原则?,java,domain-driven-design,aggregate,Java,Domain Driven Design,Aggregate,我是DDD的新手,所以我只了解DDD的基本概念。有人能给我介绍一下DDD中的聚合对象吗?特别是,为什么要使用“聚合”对象,以及在设计聚合时要应用哪些关键原则 谢谢,聚合是一致性边界 这是一个允许您指定哪些实体可以原子化更改,哪些不能更改的概念。 这也使得聚合成为通过存储库加载和持久化数据的主要容器,即存储库处理整个聚合,而不是单个实体 为了找到合适的聚合设计,您需要充分了解您的用例,并尝试找出哪些实体需要在一个事务中进行原子化更改,以及在哪里可以求助于最终的一致性。尽量使聚集体小,但总是首先考虑

我是DDD的新手,所以我只了解DDD的基本概念。有人能给我介绍一下DDD中的聚合对象吗?特别是,为什么要使用“聚合”对象,以及在设计聚合时要应用哪些关键原则

谢谢,

聚合是一致性边界 这是一个允许您指定哪些实体可以原子化更改,哪些不能更改的概念。

这也使得聚合成为通过存储库加载和持久化数据的主要容器,即存储库处理整个聚合,而不是单个实体

为了找到合适的聚合设计,您需要充分了解您的用例,并尝试找出哪些实体需要在一个事务中进行原子化更改,以及在哪里可以求助于最终的一致性。尽量使聚集体小,但总是首先考虑用例。 这是一个允许您指定哪些实体可以原子化更改,哪些不能更改的概念。

这也使得聚合成为通过存储库加载和持久化数据的主要容器,即存储库处理整个聚合,而不是单个实体


为了找到合适的聚合设计,您需要充分了解您的用例,并尝试找出哪些实体需要在一个事务中进行原子化更改,以及在哪里可以求助于最终的一致性。尽量使聚集体小,但总是首先考虑用例。

让我们从一开始就开始。很久以前,在一个很远很远的星系里,有一个SQL数据库。我们在这里真正感兴趣的是来自酸性ancronym的原子性和一致性。例如,如果您有两个更改

a1->a2
b1->b2
,并且您在这样的事务中进行了更改,那么这些更改必须是原子的,并且您只有两个有效的状态选项:
a1、b1
a2、b2
。因此,如果
a1->a2
更改失败,那么整个事务将失败。这称为即时一致性

相比之下,有一些noSQL数据库不符合ACID。通过这些数据库,您的更改不是原子的,您可以有多种状态:
a1、b1
a2、b1
a1、b2
a2、b2
,具体取决于更改的顺序或失败的更改。这就是所谓的最终一致性

如果您有一个分布式系统,其中包含涉及多台计算机的复杂更改,那么您有两个选择。您可以使用最终一致性,这将非常快,但数据在多台计算机上不一致。或者,您可以使用即时一致性,更新速度将非常慢,但计算机之间的数据将保持一致

根据DDD,聚合是一个一致性边界:内部变化具有即时一致性,外部变化具有最终一致性。为了继续使用相同的示例,您需要使用命令更改两件事:
a1->a2
b1->b2
。如果这些内容在同一个聚合中
x
,则可以在同一事务中更改它们:
(x.a1,x.b1)->(x.a2,x.b2)
,使用即时一致性。如果这些内容处于不同的聚合中:
x
y
,那么您不能在同一事务中更改它们,因此您必须使用最终一致性:
x.a1->x.a2
y.b1->y.b2
将是两个独立提交的事务

根据弗农的书,DDD有一条规则;不能在一个事务中更改多个聚合。如果您这样做,那么它就是一种代码气味,这是一种以不同方式选择一致性边界的标志,或者用其他术语来说,以不同方式设计聚合

因此,通过设计聚合,您必须记住这些一致性边界。如果不这样做,则会导致并发问题。例如,在聚合
x
上有
a
b
属性。这些属性彼此独立,因此
(x.a1,x.b2)
(x.a2,x.b1)
都是有效状态。如果John想要在两个并发请求中更改
x.a1->x.a2
而Jane想要在两个并发请求中更改
x.b1->x.b2
,那么其中一个请求将失败,尽管这两种情况都是:
(x.a1,x.b1)->(x.a2,x.b1)->(x.a2,x.b2)
(x.a1,x.b1)->(x.a2,x.b2)
将导致相同的状态
(x.a2,x.b2)
,并且每个步骤都有效。因此,约翰或简如果同时在同一个集合上工作,那将是糟糕的一天。如果它们发送多个并发请求,则可能同时发送这两个请求。您可以通过创建新的聚合
y
并将
b
属性移动到该聚合中来解决此问题。因此,在两个事务中,更改将是
x.a1->x.a2
y.b1->y.b2
,这不会造成麻烦

如果有两个聚合
x
y
,并且属性
x.a
y.b
不能独立更改,则反例为。因此
x.a1、y.b2
x.a2、y.b1
状态无效。这是将这两个聚合合并为一个并使用即时一致性而不是最终一致性的标志

您的系统很有可能在多台机器上运行。较大的组件(如有界上下文)聚合最终将保持一致,而较小的组件(如值对象)实体将立即保持一致。因此,您可以在多台计算机上部署有界上下文,而无需分布式事务和两阶段提交,这将导致快速可靠的