再论 Java 应用中的“领域建模”

摘要:
然而,这与JavaEE规范中的分层概念有些冲突,显然与EJB3编程模型有冲突。“公认的”问题EJB3&JPA是众所周知的。EJB3+JPA编程模型是一种典型的贫血模型,是JavaEE提倡的最佳实践,也是唯一的正统编程模型。
再论 Java 应用中的“领域建模”

转载请保留作者信息:

作者:88250

Blog:http:/blog.csdn.net/DL88250

MSN & Gmail & QQ:DL88250@gmail.com

  1. 再论 Java 应用中的“领域建模”
    1. 相关术语与概念
      1. POJO(Plain Old Java Object)
      2. 领域模型(Domain Model)
      3. 各种风格(Style)的领域模型
        1. 贫血的领域模型(Anemic Domain Model)
        2. 富领域模型(Rich Domain Model)
    2. “公认”的问题
      1. EJB 3 & JPA
      2. Domain Logic vs Business Logic
    3. 结论
    4. 参考列表

最近又重新整理了一下项目中领域模型建模的思路。记得范凯(robbin ) 在 2005 年时候总结的四种风格的“领域模型”及其一些变种相信大家的耳熟能详了。以现在的观点来看,不管其划分是否合理,是否适合任何项目,讨论都是有意义的。从 2004 年到 2008 年来领域模型的话题一直都是各个技术论坛、邮件列表必讨论的话题之一,这里我只是想就‘领域模型建模’这个问题发表一下我的观点,相信讨论还会继续下去,这才是本质——演化。这里的观点都是基于 Java 环境上的应用展开的,其他语言环境另当别论。

相关术语与概念

首先,让我们澄清一些相关术语与概念。很多时候发现大家讨论问题前都没有一个共同的基本假设作为前提,导致了问题越讨论越混乱,引入的其他问题越来越多。这里,我先对本文涉及的几个非常基本的概念做个统一的假设。

POJO(Plain Old Java Object

POJO 是一个简单的、常规的 Java 对象,它包含业务逻辑处理或持久化逻辑等,但不是 JavaBean、EntityBean 等,不具有任何特殊角色并且不继承/不实现任何其它 Java 框架的类或接口(java.io.Serializable 除外)。例如下面这个类就是一个 POJO,注意业务逻辑方法:

/**
* A POJO user description.
* @author 88250
* @version 1.0.0.0, Jan 15, 2009
*/
public class User implements Serializable {
/**
* user name.
*/
private String name;
/**
* Default constructor.
*/
public User() {
}
/**
* User login business logic.
*/
public void login() {
// ....
}
/**
* Gets the name of this user.
* @return the value of name
*/
public String getName() {
return name;
}
/**
* Sets the name of this user.
* @param name new value of name
*/
public void setName(String name) {
this.name = name;
}
}

从 OO 的角度看,这是一个纯粹的 Java 类,它拥有状态与行为,这也就构成了这个 User 类的职责。可惜现在 POJO 这个词简直是滥用啊,大家都认为只要描述的是一个领域实体,一个纯数据类就是 POJO 了

领域模型(Domain Model

根据 Martin 大叔的解释,领域模型就是统一了行为数据对象模型 。从 OO 的角度上看是没有任何难点与疑问的,但是开始对具体项目着手进行 OO 设计的时候问题就很多了,后面将阐述一些在实施领域模型建模时“公认”的问题。再来看看 Wikipedia 上关于领域模型的解释 ,其中涉及到了“领域层(Domain Layer ) ”这个概念,并且说明了DDD 中的领域模型是领域层的一个部分 。如下图:

再论 Java 应用中的“领域建模”第1张

根据 Wikipedia 上的解释,领域层与业务层 是同一个概念,这样划分的确是纯粹的 DDD。不过,这与 JavaEE 规范中的分层理念有一点冲突,与 EJB 3 编程模型有着明显的冲突。

各种风格(Style)的领域模型

这里的“风格”是按照 Martin 的观点进行阐述的。在以往的讨论 中,有四种可行的模型:

  • 失血模型
  • 贫血模型
  • 充血模型
  • 胀血模型

这四种模型基本是 robbinJavaEye 社区思考、讨论的结果。但我认为还是按照 Martin 的提出的模型进行讨论比较简洁,有两种可行的模型:

  • 贫血的领域模型(Anemic Domain Model)
  • 富领域模型(Rich Domain Model)

贫血的领域模型(Anemic Domain Model

贫血的领域模型就是在领域对象中 包含了 accessors 方法,默认的构造器,不包含任何逻辑处理。而逻辑处理放置于 xxxManager 中,使用事务脚本(Transaction ScriptPoEAA )进行操作。

富领域模型(Rich Domain Model

富领域模型就是 DDD 中所描述的模型,完全的 OO Concerns

“公认”的问题

EJB 3 & JPA

众所周知,EJB 3 + JPA 的编程模型是典型的贫血模型,也是 JavaEE 所推广的最佳实践 ,唯一正统的编程模型。 在这个模型中,EJBs 扮演了业务逻辑处理的角色,在分层设计中处于服务层 / 业务层。而 JPA entities 则扮演了典型的纯稚数据类 ,其行为完全由 EJBs 负责。这些也许与早先的 SSH 这样一个无状态 框架组合那么深入人心密切相关吧。目前来说,Seam 框架 / WebBeans 规范是解决客户端与服务端状态问题的较好实现与规范。另外,Seam 中的 Entity 也是可以作为 Component 而 inject / outject 的,所以 Seam 有在尝试 提供一个 DDD 的框架给开发者。

Domain Logic vs Business Logic

如果你是一个 DDD 的纯粹拥护者,不存在区分领域逻辑与业务逻辑,统称为领域逻辑。下面这个划分领域逻辑与服务逻辑是针对类 EJB 3 + JPA 纯粹用户者的。
Domain 业务逻辑(Domain Logic)与 Service 业务逻辑(Business Logic)划分的原则:

  1. 根据是否依赖持久化逻辑划分
    领域模型只包含不依赖于持久化 的领域逻辑,而那些依赖持久化的领域逻辑应该被分离到 Service 层
  2. 使用 Rod Johnson 的"case by case"原则
    可重用度高的,和 domain object 状态密切关联 的放在 domain 中,可重用度低的,和 domain object 状态没有密切关联的放在 Service 中

这样,貌似是解决了 Java 应用中使用“正统”方式(JavaEE 规范)实现领域驱动开发。但是,这样不觉得过于复杂和画蛇添足吗?

结论

领域模型驱动的设计(DDD)是需要开发团队在特定行业中积累 到一定的时候才能真正做到的,这涉及到了企业(客户)的核心价值实现与业务实现重用 ,如果不是本着这个最终目的 ,Java 下的 DDD 慎用。在建模你的 Java 项目时,一定要对项目的 Scope 做好分析,认真做好技术选型。一般来说,贫血模型(Anemic Domain Model)是最容易设计和实现的,也足够满足一般 Java Web 项目了。而领域模型(Rich Domain Model)是用在复杂 JavaEE 项目上的(例如实施 SOA 时),切勿杀鸡用牛刀 :-)

参考列表

下面的文章是精华中的精华,有兴趣、时间的朋友一定不要错过 :-)

免责声明:文章转载自《再论 Java 应用中的“领域建模”》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇关于php使用xpath解析html中文乱码问题Linux定时任务(crond)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

django集成ansibe实现自动化

动态生成主机列表和相关参数 def create_admin_domain(admin_node): workpath = BASE_DIR + '/tools/ansible/script' hosts_file = BASE_DIR + '/tools/ansible/host/' + createhostfile() yml...

crossdomain.xml跨域配置文件的安全注意事项

零、绪论: 对WEB中的FLASH确实了解不多,对程序中的跨域配置也了解不多,这是自己以前写的一篇笔记,到现在也还了解不深,勉强记下来罢了,备忘。 一、什么是crossdomain.xml?这是一个flash在跨域传输请求数据时要遵循的一个规则配置文件。例如a.com中swf文件要请求b.com中的数据,要检查该文件,如不存在则一律禁止跨域数据传输,如果存...

libvirt(virsh命令介绍)

有了virt-install是安装虚拟机的命令,当然也需要一个管理虚拟机的命令了,那就是virsh。 virsh命令使用 virsh <command> <domain-id> [OPTIONS] virsh既有命令行模式,也有交互模式,在命令行直接输入virsh就进入交互模式,virsh 后面跟命令参数,则是命令行模式。下面主要介...

Entity Framework之深入分析

EF虽然是一个晚生畸形的ORM框架,但功能强大又具有灵活性的,给了开发人员一定的发挥空间。因为微软出发点总是好的,让开发变得简单,但实际上不是所有的事情都这么理想。这里顺便推荐马丁大叔的书《企业应架构模式》。 本节主要深入分析EF的分层问题,下面是本节的已列出的要探讨内容。 领域模型的概念 DbContext与Unit of Work 的概念 DbCon...

arm 添加 samb 文件共享

编译环境: ubunto 12 arm-linux-gcc 4.3.2 arm linux 4.1.36 开发板 2440 测试上传速度,大文件 github源码 https://github.com/samba-team/samba 测试了几个版本,各有问题。 samba-4.6.2 ~ 3.6 需要安装 python 环境,才能编译。4.6 需要...

DDD从入门到精通:基础篇

这篇文章主要还是表述清楚DDD相关的基础概念,因为DDD入门有一定的专业名词,还是得有个基本的了解。 先讲解下领域模型作用: 对软件需求进行设计,维持其内在逻辑的一致性 1)划分边界、也是一种高内聚、低耦合 2)所有逻辑都是内聚在对象内部的【包含行为和数据】   为什么需要DDD? 行业现状:   贫血模型、充血模型   领域模型就是DDD? 其实领域...