需要的意见:连接或断开域模型中的实体更好吗?

Posted

技术标签:

【中文标题】需要的意见:连接或断开域模型中的实体更好吗?【英文标题】:Opinions wanted: is it better to connect, or disconnect, the entities in the domain model? 【发布时间】:2008-10-15 07:53:05 【问题描述】:

我正在开始一个新项目;我希望遵循 DDD 方法。我们已经与业务部门进行了交谈,并在某些细节(互联网电视)方面获得了对该领域的一些了解。

这支队伍由五人组成,分布广泛。我们采用了存储库模式进行数据访问。我们总体上遵循基于服务的方法;服务负责执行操作,我们将通过 REST API 公开一些操作,并通过我们自己的客户端应用程序公开一些操作。

没有使用 ORM 经验的人(目前我也没有大量经验)希望对实体之间没有关系的实体进行建模,其理由是这迫使使用存储库的开发人员准确了解他们对数据库有什么影响。我想指出的是,这最终会导致一组非常健谈的服务、更多需要维护和测试的代码,以及一个根本没有抓住重点的领域模型。我认为这不是一个好方法,我与之交谈过的任何人都没有。

他们希望实现这种方法的是存储库外观下的 Linq2SQL。这需要第二个模型,它与域模型之间的映射类/层,以及存储库中的大量重复,因为编写通用存储库似乎是不可能的(我们目前已经看到)。也无法映射利用继承的 L2S 实体(这意味着每个实体都必须具有 created-on、created-by 等属性)

第一个问题: 谁能给我任何关于如何改变主意的建议?我正在编写一个使用 NHibernate 的辅助项目,它当然很好地支持 DDD 方法,基于“给我看代码”是一个强有力的论点。

第二个问题: 我应该尝试在我的 NHibernate-using on-my-own-time 副项目中演示什么样的事情?我是新手;他们对 NHibernate 的厌恶之一是学习曲线和对 XML 的要求;我的反驳是它是一个强大的工具,而且 Fluent NHibernate 消除了对 XML 的需求。他们仍然不喜欢它。

【问题讨论】:

我使用 Linq2Sql 的通用存储库:iridescence.no/post/… 【参考方案1】:

您是否看过 DDD 中聚合根的概念?基本上,您只需从存储库中请求聚合根,然后加载整个聚合。聚合具有执行所需操作所需的一切,这样可以消除您对闲聊的担忧,也可以解决您的团队对明确加载内容的担忧。

在您的辅助项目中,演示一个基于聚合根的存储库,该聚合根加载整个聚合。这是相当直接的代码,其意图非常明确。不幸的是,您仍然必须顺应 NHibernate 学习曲线,但如果您使用这种方法,那么“魔法”就会减少。

【讨论】:

【参考方案2】:

根据您的描述,我猜您正在构建的每个服务都以特定实体为中心,当您的域模型想要不同的实体时,它需要使用不同的服务。

如果是这种情况,我会建议服务过于细化。我建议围绕需要完成的流程为您的服务构建接口,并使用这些服务实现的域模型部分。我的理解是 SOA 提倡将系统公开为一组服务,但是单个系统的组件之间的内部交互不应该是服务。

这种方法产生了一个丰富的域模型,使用聚合根作为将实体关联在一起的一种方式和存储库的基础,服务位于这种暴露粗粒度行为之上,而不是与任何单个实体的基本交互。系统内部的客户端应用程序可以提供此功能(使用相同的域模型)。

如果模型中的实体是相关的,并且这些关系对系统的行为很重要,那么应该强制执行这些关系(因此系统会反映被建模的域),如果每个实体都是独立的,这将很难做到,特别是如果它们是服务。

您最终会得到一个系统,其中所有实体服务都需要相互调用(创建大量耦合、增加变更管理开销等),否则您将无法强制执行这些关系,这意味着稀释您的模型并可能导致行为不一致或数据丢失。

这将从根本上归结为高内聚和低耦合的基本原则,它们是相反的力量,有必要在解决方案中尝试平衡它们。如果您没有关系(或隐式关系),那么您会以内聚为代价获得低耦合,并且如果确实存在未表示的关系或在更高级别增加依赖关系,则可能会产生维护问题。如果你强烈地强制执行过多的关系,你最终会导致你的领域模型变成一团泥球并且变得难以管理。这方面的具体建议很困难,但通常我会先用聚合构建模型,专注于聚合内部的关系并经常审查模型。

特别是在 NHibernate 上,我建议展示它提供的简洁抽象、所需代码的减少、无需更改代码的简单配置以及提供的功能数量,例如身份地图和工作单位等。

【讨论】:

【参考方案3】:

由于我没有使用过休眠,因此无法提供具体信息。但适用于几乎所有类似情况的一般事实是:

“让一切尽可能简单,但不要更简单。” - 艾尔伯特爱因斯坦

所以我的意见是尽可能使用最少的连接来保持系统的良好定义。并且避免尝试连接所有东西,因为它会在后面咬你(记住编程中的松散耦合原则)

【讨论】:

【参考方案4】:

您的团队似乎只是将 ORM 用作将数据库映射到一组具体类的一种方式,以使代码更好一些。如果您想创建一个域模型而不仅仅是一个抽象的数据库模型,那么显然您应该包含关系。如何在后台加载数据是另一回事。

【讨论】:

以上是关于需要的意见:连接或断开域模型中的实体更好吗?的主要内容,如果未能解决你的问题,请参考以下文章

DDD 域实体与持久性实体

嵌套查询与连接查询的区别是啥

使用 ORM 生成的实体作为多态的域对象

数据库设计模型实体关系图n实体与1:m实体的关系 - 最佳实践

xmpp服务器的客户端可以断开其他客户端与服务器的连接吗?

荣耀手表ES与运动健康App蓝牙连接自动断开或无法自动重连?