在简单的域驱动设计中的贫血域模型与域模型

时间:2009-07-21 00:05:58

标签: design-patterns anti-patterns

我最近阅读了一篇引起我注意的“The Anemic Domain Model Pattern”帖子。当我读完这篇文章时,我发现贫血领域模型描述适用于我所研究和构建的许多项目。我从未认为这是一个糟糕的设计决定,因为它感觉非常自然。我认为,在domain model重量轻且不是很复杂的情况下,贫血领域模型的名字非常适合。为什么要增加域模型的复杂性,而不仅仅是因为“贫血领域模型”的标题不能恰当地描述你的代码呢?

问题:在您的服务/应用程序层填充更多代码复杂性的时间点变得不正确,有利于暴露实体对象的复杂性?我在一个实体上拥有一个“Total”属性,它在内部可以计算出Total的值。我不是让实体直接与各种其他小工具通信,以确定其中一个属性的结果。因此,贫血领域模型的概念是一种反模式还是一种良好的关注点分离?标题贫血领域模型总是一件坏事吗?

只是好奇其他人对这种设计(反)模式的想法。

3 个答案:

答案 0 :(得分:9)

关键问题是问为什么域模型贫血?

  • 几乎完全没有业务逻辑,就像主要是CRUD screens的组合的应用程序一样?
  • 面向服务的体系结构,其中“域对象”实际上是简单结构 data transfer objects
  • 政治或实用的考虑因素,例如代码所有权或向前/向后兼容性会过度阻碍重构?
  • 在面向对象的语言中应用程序/关系设计?

在任何情况下,如果我要为域模型逻辑和服务逻辑之间的边界选择一个简单的经验法则,那么在访问“外部世界”时,与域中的相关对象进行交互是很好的。用户界面,Web服务等)可能不属于域模型。

答案 1 :(得分:7)

如果域是轻量级的(读取:不复杂),建议的方法是在核心域层中使用简单的ActiveRecord类型对象。通常是数据库表和域对象之间的一对一映射,这里没有很多“逻辑”。您的应用程序只是在数据库和UI之间移动记录并允许简单的CRUD操作。

对于复杂域,您将构建一个核心域模型,其中一些对象最终映射到数据库表,有些可能不会并且代表域中的其他概念,除了纯数据。应用程序的逻辑应该在适当的时候位于对象内部,或者如果它需要多个域对象之间的协调,则应该位于Service对象中。

Anemic Domain Model反模式适用于您拥有复杂域但不是在域对象和服务中的某些逻辑中适当地放置一些逻辑时,您将所有(或几乎所有)逻辑放在核心域的外部对象。

这里的关键区别在于您放置逻辑。如果你没有太多,显然域对象看起来只不过是简单的数据容器。如果你确实有复杂的逻辑,不要只从域对象中提取它,而是在核心域对象和域服务之间适当地分开它。

答案 2 :(得分:1)

天儿真好!

如果将逻辑置于域对象之外,则会完全失去一个主要的OO概念:封装(或数据隐藏)。

AOP达到了一定程度,但毕竟,面向对象的一个​​关键概念已经消失。

此致 斯蒂芬