首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET中的DDD / Aggregates

.NET中的DDD / Aggregates
EN

Stack Overflow用户
提问于 2011-07-06 04:59:23
回答 5查看 1.6K关注 0票数 6

我一直在读埃文斯关于DDD的书,正在思考如何在.NET中实现聚合。目前,我只能想出一种方法:将聚合隔离在单独的类库中。然而,这似乎有点过头了(我更喜欢将所有的域对象保存在一个库中),我想知道是否有不同的方法?

1库/聚合的理由如下:聚合根需要知道它负责的对‘子对象’的所有访问,并且聚合根可以返回子对象作为其成员的结果。因此,这些子对象的成员(聚合根所需)不能公开。因此,您唯一的选择是将它们设为内部(因为它们仍然需要由聚合根调用)。但是,通过将所有聚合放在一个项目中,仍然可以从获得该子对象的其他域对象访问这些成员。这是不可取的,因为它允许绕过聚合根。通过将所有聚合分离到不同的库中,这个问题就解决了。

一些附加信息:

我检出了DDD java sample code,它们将每个聚合(包括所有子对象的类)打包到一个不同的包中。只能从聚合根调用的成员没有访问修饰符(例如:Delivery.updateOnRouting)。在java中,没有访问修饰符的成员是package-private (只能从相同的包中获得)。所以这将是正确的行为。

但是,.NET sample code将所有域对象放在一个类库中,然后使相应的成员成为公共成员。在我看来,这似乎是不正确的。

EN

回答 5

Stack Overflow用户

发布于 2011-07-07 08:08:26

聚合是DDD中最难的概念之一。你大部分都说对了。我建议用聚合的“成员”来表达这个概念,比引入术语“子对象”更直接。

是的,一个对象不能是多个聚合的成员。哪一个会是最终的执行者?通过删除成员并孤立其他聚合中的其他成员,一个聚合根可以很容易地使另一个聚合无效。你是对的,在一个对象似乎需要多个聚合中的成员的情况下,该对象必须是一个独立的实体,即它成为新聚合的根。(它可能有也可能没有其他成员,但如果没有,那么它当然会成为它自己的一个聚合。)

是的,聚合的存在是绝对正确的,以强制执行不变量。就持久性而言,它也是单个工作单元或单个事务。聚合根最终负责其整个成员关系中的所有不变式,这肯定是因为,例如,不变式的失败可能导致持久性失败,而聚合负责将聚合作为一个可行的持久性工作单元进行维护。

然而,这是微妙和困难的部分,最终的责任并不意味着聚合也是的主要实施者。就像我们在司法系统中所做的那样--法院最终是决定法律问题的最终地点,在那里实施最终的法律规则,执行不变的东西。但实际的强制执行(和遵从性)发生在系统的许多级别。事实上,在一个井然有序的社会中,大多数实施法治的活动--执行不变量--应该在你去法院之前很久就发生了,你根本不应该依赖于例行公事地去法院。(尽管在DDD中,您可能总是想让聚合根在持久化之前执行最后一次不变扫描。)

你的建议是完全不同的,基本上你的整个社会都被监禁了,除了法庭之外,你似乎甚至提议其他人甚至不能访问,他们只能向法庭传递一个信息,并希望它采取适当的行动。

让我们看看如果您遵循您建议的路径,您的域会发生什么情况。我们的目标是创建一个丰富且富有表现力的领域模型。在有意义的无处不在的语言方面,您已经将您的工作词汇表减少到仅聚合词根。由于不变量的原因,一个实体应该被聚合根访问,但也因为如果设计是正确的,该实体具有有意义的标识,该标识是由它在聚合根上下文中的成员身份产生的。但是你的提议一个实体在它的聚合根之外甚至没有任何类型标识.Evans特别指出,这是聚合根的目的之一--允许对象通过遍历获得对成员的引用。但是您无法获得有用的引用,因为另一个对象甚至不知道您的成员类型存在。或者,您可以更改名称空间,但如果您不允许遍历,这也不会更好。现在你的整个领域都知道类型,但是对象的类型是永远无法获得的。

更糟糕的是,您的聚合根发生了什么。除了维护聚合完整性之外,聚合根通常还应该有自己的存在理由。但现在,这个身份已经不再清晰。因为需要为所有不同的元素及其属性提供一个包装器方法,所以它被遮蔽了。你得到的是聚合的根,它们不再具有表现力,甚至不再具有明确的身份,只有庞大而笨拙的上帝对象。

您的Order和OrderLine示例就是一个有趣的例子。该命令没有提供代表OrderLine的OrderLine所需的某些不变量的强制执行。在这种情况下,它控制操作以强制执行它自己的不变式。这是对聚合根进行控制的有效操作。然而,更典型的聚合主要涉及对象的创建和/或销毁。

当然不需要引入模型,其中状态中的所有更改都必须由聚合根自动应用,而不是直接应用。实际上,这通常是聚合根允许遍历以获取对成员的引用的原因-因此外部对象可以应用状态更改,但在聚合控制被更改的成员实体的实例生命周期的上下文中。

不仅是可见性,而且与更大领域的实际交互通常是开发丰富且富有表现力的模型的基础。聚合用于控制该访问,但不能完全消除它。

我希望这能有所帮助,这是一个很难讨论的概念。

票数 6
EN

Stack Overflow用户

发布于 2011-07-06 05:26:05

我只能想出一种方法;将聚合隔离在单独的类库中。然而,这看起来有点过头了。

更像是lot of overkill。这样做的开销将是残酷的,你不想几十个项目,这种方法在任何不平凡的应用程序中创建的项目。

票数 2
EN

Stack Overflow用户

发布于 2011-07-06 08:54:51

代码语言:javascript
复制
Therefore, members (needed by the aggregate root) of these sub-objects can't be made public.

我认为这一结论过于僵化,不切实际,也不是埃文斯所提倡的。是的,他确实说过Agg Root负责创建和访问该Root中的其他对象,但是

首先,聚合根有重叠的趋势。如果一个小部件需要放在两个不同的根中,不管出于什么原因,它都是必需的。因此,您真的不能让它(在本例中是小部件)只对一个Root可用,而对另一个根不可用。

其次,我认为(我的解释和我没有这本书!)关于对象访问的Agg根的想法更多的是一种约定而不是教条。教条是在该根目录的上下文中满足客户端请求,以便简化域。它更多的是为Aggregate Root开发一个接口,然后让客户端通过该接口来满足他们的需求。如果您可以限制对(任何)客户端不需要的对象的访问(使用任何聚合根),那么一定要这样做。

HTH,

Berryl

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6588792

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档