在域驱动的设计中,为什么要使用“聚合”对象?在设计聚合时将应用哪些关键原则? [英] In domain driven design, why would you use an “aggregate” object and what key principles would you apply when designing an aggregate?

查看:90
本文介绍了在域驱动的设计中,为什么要使用“聚合”对象?在设计聚合时将应用哪些关键原则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是DDD的新手,所以我只是了解它的基本概念。有人可以指导我更多地介绍DDD中的聚合对象吗?特别是,为什么要使用聚合对象,以及在设计聚合时将应用哪些关键原则?

I am new to DDD, and so am just understanding the basic concepts around it. Can someone please guide me more towards aggregate objects in DDD? particularly, why would you use an "aggregate" object and what key principles would you apply when designing an aggregate?

谢谢,

推荐答案

让我们从头开始。很久以前,在一个遥远的星系中,有一些具有 ACID交易的SQL数据库。我们真正感兴趣的是ACID首字母缩略词的原子性和一致性。例如,如果您有两个更改 a1-> a2 b1-> b2 并且您在这样的事务中进行更改,那么更改必须是原子性的,并且只有两个有效的状态选项: a1,b1 a2,b2 。因此,如果 a1-> a2 更改失败,然后整个事务失败。称为立即一致性。

Let's start it from the beginning. A long time ago in a galaxy far, far away there were SQL databases with ACID transactions. What we are really interested here are the atomicity and consistency from the ACID ancronym. For example if you have two changes a1 -> a2 and b1 -> b2 and you make them in such a transaction then the changes must be atomic and you will have only 2 valid state options: a1, b1 and a2, b2. So if the a1 -> a2 change fails, then the whole transaction fails. This is called immediate consistency.

相比之下,没有SQL数据库不兼容ACID。通过这些数据库,您的更改不是原子的,并且您可以具有多个状态: a1,b1 a2,b1 a1,b2 a2,b2 ,具体取决于进行更改的顺序或更改失败。这称为最终一致性。

In contrast there are noSQL databases, which are not ACID compliant. By these databases your changes are not atomic and you can have multiple states: a1, b1, a2, b1, a1, b2, a2, b2, depending on what order the changes are made or which changes fail. This is called eventual consistency.

如果您的分布式系统具有涉及多台计算机的复杂更改,则有两个选择。您可以使用最终的一致性,这将非常快,但是数据在多台计算机上将不一致。或者,您可以使用两阶段提交的即时一致性,并且更新将非常缓慢,但数据在机器之间是一致的。

If you have a distributed system with complex changes which involve multiple computers, then you have two options. You can use eventual consistency, which will be very fast, but the data won't be consistent on multiple machines. Or you can use immediate consistency with 2 phase commit, and the updates will be very slow, but the data will be consistent between the machines.

通过DDD,聚合是一个一致性边界:内部变化具有直接一致性,外部变化具有最终一致性。坚持同一示例,您想使用命令更改2件事: a1-> a2 b1-> b2 。如果这些内容在同一汇总 x 中,则可以在同一事务中更改它们:(x.a1,x.b1)-> ; (x.a2,x.b2)使用即时一致性。如果这些东西在不同的汇总中: x y ,则您无法在同一事务中更改它们,因此您必须使用最终的一致性: x.a1-> x.a2 y.b1-> y.b2 将是彼此独立执行的两个事务。

By DDD the aggregate is a consistency boundary: the inside changes with immediate consistency and the outside changes with eventual consistency. To stick with the same example, you want to change 2 things with your command: a1 -> a2 and b1 -> b2. If these things are in the same aggregate x, then you can change them in the same transaction: (x.a1, x.b1) -> (x.a2, x.b2) using immediate consistency. If these things are in different aggregates: x, y, then you cannot change them in the same transaction, so you have to use eventual consistency: x.a1 -> x.a2 and y.b1 -> y.b2 will be the two transactions which will be committed independently from each other.

根据维农的书,DDD有一条规则;您不能在单个交易中更改多个汇总。如果这样做,则会产生代码异味,这是选择不同的一致性边界的标志,或者换句话说,是对聚合进行不同的设计。

By DDD there is a rule according to Vernon's book; you cannot change multiple aggregates in a single transaction. If you do so, then it is a code smell, which is a sign to choose the consistency boundaries differently, or in other terms design the aggregates differently.

因此,通过设计聚合时,您必须牢记这些一致性边界。如果您不这样做,则会导致并发问题。例如,您在总计 x a b 个属性>。这些属性彼此独立,因此(x.a1,x.b2)(x.a2,x.b1)是有效状态。如果约翰想更改 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.a1,x.b2)-> (x.a2,x.b2)将导致相同的状态(x.a2,x.b2),并且每个步骤均有效。因此,John或Jane会因为同时处理同一个聚合而日子不好过。如果它们同时发送多个并发请求,则可能两者都使用。您可以通过创建新的聚合 y 并将 b 属性移到其中来解决此问题。因此更改将是 x.a1-> x.a2 y.b1-> y.b2 进行两次交易,不会造成麻烦。

So by designing aggregates you have to keep in mind these consistency boundaries. If you don't do so, then it will cause concurrency issues. For example you have a and b properties on your aggregate x. These properties are independent from each other, so either (x.a1, x.b2) and (x.a2, x.b1) are valid states. If John wants to change x.a1 -> x.a2 and Jane wants to change x.b1 -> x.b2 in two concurrent requests, then one of the requests will fail despite the fact, that both scenarios: (x.a1, x.b1) -> (x.a2, x.b1) -> (x.a2, x.b2) and (x.a1, x.b1) -> (x.a1, x.b2) -> (x.a2, x.b2) would result the same state (x.a2, x.b2) and each of the steps are valid. So either John or Jane will have a bad day by working on the same aggregate simultaneously. Probably both of them if they send multiple concurrent requests. You can resolve this problem by creating a new aggregate y and moving the b property into that. So the changes will be x.a1 -> x.a2 and y.b1 -> y.b2 in two transactions, which won't cause trouble.

如果您有两个聚合的相反示例 x y 以及属性 xa yb 不能独立更改。因此 x.a1,y.b2 x.a2,y.b1 状态无效。这是将这两个聚合合并为一个并使用立即一致性而不是最终一致性的标志。

The inverse example if you have two aggregates x and y and the properties x.a and y.b cannot change independently. So the x.a1, y.b2 and x.a2, y.b1 states are invalid. This is a sign to merge these two aggregates into one and use immediate consistency instead of eventual consistency.

您的系统很有可能在多台计算机上运行。较大的组成部分(如有限上下文)将最终保持一致,而较小的组成部分(如值对象,实体)将​​立即保持一致。因此,您可以在多台计算机上部署有限的上下文,而无需进行分布式事务和两阶段提交,这将导致系统快速可靠。另一方面,由于您使用聚合,聚合只能具有有效状态。

There is a good chance that your system will run on multiple machines. The bigger components, like bounded contexts, aggregates will be eventually consistent, while the small ones, like value objects, entities will be immediately consistent. Thus you can deploy your bounded contexts on multiple machines without distributed transactions and 2 phase commit, which will result a fast and reliable system. On the other hand the aggregates can have only valid states thanks to the transactions you use by them.

请注意,我不是该主题的专家,我只是阅读了书。 =]

Note that I am not an expert of the topic, I just read a book. =]

1y之后:

我发现了一个非常关于聚合的好文章。根据它,您应该在不变量周围设置一致性边界,以防止违反合同。因此,如果您有不变量的列表,则可以使用它们来定义一致性边界。总体边界将相似。理想情况下,它们包括每个不变式,但是如果它们变得太大,则会导致太多的并发异常,因此在复杂的情况下,它们将不包括某些不变式。

I found a very good article about aggregates. According to it you should put consistency boundaries around invariants to prevent contract violation. So if you have a list of invariants, then you can use them to define consistency boundaries. Aggregate boundaries will be similar. Ideally they include every invariant, but if they grow too big, they will result too many concurrency exceptions, so in complex cases they can't include some of the invariants.

这篇关于在域驱动的设计中,为什么要使用“聚合”对象?在设计聚合时将应用哪些关键原则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆