领域驱动设计中实体和聚合之间的区别

Posted

技术标签:

【中文标题】领域驱动设计中实体和聚合之间的区别【英文标题】:Difference between an entity and an aggregate in domain driven design 【发布时间】:2015-11-28 00:02:46 【问题描述】:

请问在领域驱动设计中实体和聚合根之间的主要区别是什么。比如在实体框架中,如果我能保证实体的数据完整性,那么聚合有什么用?

【问题讨论】:

【参考方案1】:

定义相当简单:

聚合:基本上是一组对象,创建对根聚合的明确引用,因此当您引用根时,您可以确保聚合作为一个整体的完整性。

聚合是领域驱动设计中的一种模式。 DDD 聚合是一个 可以被视为一个单元的领域对象的集群。一个 示例可能是订单及其订单项,这些将是分开的 对象,但处理订单很有用(连同它的行 项目)作为单个聚合。

聚合将使其组件对象之一成为聚合 根。来自聚合外部的任何引用都应该只转到 聚合根。因此,根可以确保数据的完整性 聚合为一个整体。

聚合是数据存储传输的基本元素 - 你 请求加载或保存整个聚合。交易不应该 跨越聚合边界。

DDD 聚合有时会与集合类(列表、 地图等)。 DDD 聚合是领域概念(订单、诊所就诊、 播放列表),而集合是通用的。聚合通常会 包含多个集合,以及简单的字段。术语 “聚合”是一个常见的,用于各种不同的上下文 (例如 UML),在这种情况下,它与 DDD 聚合。

实体:在数据模型上下文中,描述数据的结构,与存储形式无关。

EDM 解决了将数据存储在 多种形式。例如,考虑一个将数据存储在 关系数据库、文本文件、XML 文件、电子表格和 报告。这对数据建模提出了重大挑战, 应用程序设计和数据访问。在设计面向数据的 应用程序,挑战在于编写高效且可维护的代码 在不牺牲高效的数据访问、存储和可扩展性的情况下。 当数据具有关系结构时,数据访问、存储和 可扩展性非常高效,但编写高效且可维护 代码变得更加困难。当数据具有对象结构时, 取舍相反:编写高效且可维护的代码 以高效的数据访问、存储和可扩展性为代价。甚至 如果可以在这些权衡之间找到适当的平衡,新的 当数据从一种形式转移到另一种形式时,就会出现挑战。这 实体数据模型通过描述 根据实体和关系的数据结构 独立于任何存储模式。这使得数据的存储形式 与应用程序设计和开发无关。而且,因为 实体和关系按原样描述数据的结构 在应用程序中使用(而不是其存储形式),它们可以演变为 应用程序不断发展。

定义可能有所不同,由 Martin Fowler 和 Microsoft 定义。希望这可以澄清差异。

【讨论】:

遗憾的是,两者的定义可以互换使用,这可能会造成混淆,但这就是每个人的实际含义。【参考方案2】:

从领域驱动设计的角度来看,DbContext 是 UnitOfWork 的实现,DbSet<T> 是存储库的实现。

这就是 DDD 和 EntityFramework 的对比点。 DDD 建议为每个聚合根创建一个存储库,但 EntityFramework 为每个实体创建一个。

那么,什么是聚合根?

假设我们有一个社交网络,并且有实体,例如 Post、Like、Comment、Tag。 (我相信你可以想象这些实体之间的关系)其中一些实体是“聚合根”

为了找到聚合根,我试图找出哪些实体没有另一个就不能生存。例如,喜欢或评论不能没有帖子。然后 Post 是一个聚合根,我们需要一个 PostRepository 或将 Post 实体变成一个 Repository(著名的集合类接口事物)。评论和点赞(以及帖子)的 CRUD 操作应保留在此存储库中。

【讨论】:

很好的答案和定义,一个更实用的定义,而不是我的理论定义。 'DDD 建议每个聚合都有一个存储库......' 恕我直言,这是一个很好但未被充分利用的概念。 “例如,Like 或 Comment 没有帖子就无法生存” 这是一种非常幼稚的组合聚合边界的方式。遵循这种想法将导致大型集群聚合,即使它完全没有必要。你真的需要加载在内存中创建的所有 cmets 只是为了添加一个新的吗?你想通过这样做来保护什么不变量?您可能在某些领域需要它,但这种设计对于大多数博客应用程序来说都是错误的。 这已经很晚了……但是这篇文章帮助我进一步理解。 [链接] (codeproject.com/Articles/1020932/…) @AlirezaRahmaniKhalili 你可以这样想。当您删除评论时,删除帖子是否也有意义?可能不是。那么这意味着 Post 可以在没有评论的情况下生存。另一方面,当帖子被删除时删除评论是否有意义?可能是。那么这意味着没有帖子,评论就无法生存。【参考方案3】:

实体:主要由其身份定义的对象称为实体,在销售系统中具有重要意义(例如客户)是实体,并且可以随时间变化。

值对象:值对象是仅通过其属性和值知道的对象。例如,“客户地址”可以设计为值对象。值对象可以分配给不同的实体,通常实现为不可变(例如日期、地址)

聚合:通过聚合根对象相互关联的实体或值对象的集合

聚合根:每个聚合都有一个根和一个边界,聚合根拥有一个聚合并充当聚合内所有修改的网关

【讨论】:

以上是关于领域驱动设计中实体和聚合之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

领域驱动设计和Spring

如何运用领域驱动设计 - 聚合

领域驱动设计和Spring(翻译)

首席架构师老曹推荐阅读:领域驱动设计和Spring

基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则

一系列简单的聚合根问题(领域驱动设计)