java - .NET中的DDD/聚合

标签 java .net design-patterns architecture domain-driven-design

我一直在阅读Evans关于DDD的书,并在思考如何在.NET中实现聚合。目前,我只能想出一种方法。将聚合隔离在单独的类库中。但是,这似乎有点矫kill过正(我宁愿将所有域对象都保留在一个库中),并且我想知道是否有其他方法吗?

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

一些其他信息:

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

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

最佳答案

聚合是DDD中最困难的概念之一。您拥有大部分权利。我建议以“成员身份”的形式总体表达这个概念比引入“子对象”这一术语更为直接。

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

是的,绝对存在强制执行不变性的集合。就持久性而言,它也是单个工作单元或单个事务。聚合根最终负责整个成员中的所有不变量,这必须是因为,例如,不变量的失败可能导致持久性失败,并且聚合负责将聚合作为一个可行的持久性工作单元维护。

但是,这是一个微妙而困难的部分,最终责任并不意味着合计也是主要强制实现者。就像我们在司法系统中所拥有的一样,法院最终是确定法律问题和施加最终法律规则的最终场所,而不变性则被强制执行。但是实际的执行(和遵从性)发生在系统的许多级别。实际上,在一个秩序井然的社会中,大多数实现法治的 Activity -对不变量的执行-应该早在上法庭之前就已经发生了,甚至根本不必依靠常规去上法庭。 (尽管在DDD中,您可能总是希望有一个聚合根,例如在持久性之前进行最后的不变扫描。)

您的建议是完全不同的,除了法院之外,您的整个社会实际上都被监禁了,您似乎甚至建议其他人甚至不能访问,他们只能向法院传递信息并希望它能适本地发挥作用。

让我们看看如果您按照建议的方式对您的域进行了处理。目的是创建一个丰富而富有表现力的领域模型。在有意义的普遍存在的语言方面,您已经将工作词汇量减少到了总的根。实体之所以应该被聚合根访问是因为不变量,而且还因为如果设计正确,则该实体具有有意义的身份,该身份是由于其在聚合根上下文中的成员身份而产生的。但是您的提案实体在其聚合根之外甚至没有任何类型标识。 Evans特别指出,这是聚合根的目的的一部分-允许对象通过遍历获取对成员的引用。但是您无法获得有用的引用,因为另一个对象甚至都不知道您的成员类型存在。或者,您可以更改 namespace ,但是如果您不允许遍历,那就更好了。现在,您的整个域都知道类型,但是无法获得对象的类型。

更糟糕的是您的聚合根发生了什么。聚合根除了维护聚合完整性外,通常还应有其自身存在的理由。但是现在这种身份不再明确。对于所有各种元素及其属性都需要有一个包装方法,这使它变得晦涩难懂。您得到的是不再具有表现力甚至清晰的身份的聚集的根,而只是庞大而笨拙的上帝对象。

您的Order和OrderLine示例就是一个有趣的例子。订单未执行代表订单行的订单行所需的某些不变式的强制执行。在这种情况下,它控制 Action 以强制执行自己的不变式。这是对聚集根进行 ionic 控制的有效措施。但是,更通常地,聚集大多数情况下与对象的创建和/或破坏有关。

当然,没有必要强加一个模型,在该模型中,状态的所有变化都必须由聚合根自动应用,而绝不能直接应用。实际上,这通常就是为什么聚合根允许遍历以获得对成员的引用的原因-外部对象可以应用状态更改,但是在聚合控制着更改的成员实体的实例生命周期的上下文中。

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

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

关于java - .NET中的DDD/聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6588792/

相关文章:

java - 无法在 JPanel 中添加标签

java - Jersey:JSON 和 StringMessageProvider 冲突,application/json 方法生成无效的 JSON

c# - 如何在 Visual Studio for C# 项目中使用自定义框架而不是 .NET?

.net - AMQP 生产准备好了吗?

java - 使用 EJB 的无状态工厂

c++ - 使用指针和使用静态对象的单例实现之间的区别

java - 如何转换两个物体

java - 如何用connectionservice实现视频

C# ToTitleCase 和文本格式的日期/时间

design-patterns - 向导用户界面的设计模式