论坛首页 Java版 领域模型

贫血的Domain Model

浏览 7280 次
该帖已经被评为精华帖
作者 正文
时间:2008-05-10
楼主的精神值得鼓励,期望更进一步的实践。

另外大家又回到去讨论domain object是否有意义的问题上了,这个问题很久以前已经讨论过了,还是那句话,去看以前的帖子吧。
   
0 请登录后投票
时间:2008-05-10
大家说的都有道理。Domain Model引入的代价是相当高的。如果系统本身业务逻辑比较少,但是体力活很多。用其他的系统架构或许成本更低,也更好维护。对于Domain Model是不是有必要,就不要在这里讨论了吧。
   
0 请登录后投票
时间:2008-05-11
陶公子的探索精神值得鼓励,作为一个程序员,我们总应该想办法把事情做到合理,所谓的水平,就是在不断探索过程中提高的。不过,
* 多人协作的项目里面,不管用怎样的方法,保持一致是最重要的。
* 指望所有人都这么编写代码是不现实的,应该让人在大多数情况下只做简单的事。

大家可以想一下,为什么大家普遍比较认可RoR中ActiveRecord的做法呢?

一个重要的原因是ActiveRecord::Base这个类替我们封装好了几乎一切。所以,在我们的Domain Model里面(至少是在那个文件里面),几乎只有我们自己的领域逻辑。就是这样的一个间接层的存在,极大限度的分离了数据库逻辑和领域逻辑。

从这个角度来说,陶公子可以继续自己的探索,将自己探索的这部分进一步封装,比如封装成一个库,让其他人可以简单的应用。
   
4 请登录后投票
时间:2008-05-11
这个库的名字都已经取好啦,叫Ferrum,铁元素。这里贴的代码其实就是Ferrum的example。我现在在写一个以CRM的Domain的大一点的例子。在写具体的例子的过程,发现都有哪些需求,从而实现一个框架。当然最终目标是大家拿过去就能用啦。
   
0 请登录后投票
时间:2008-05-11
taowen 写道
pig345 写道
DomainObject为什么不能直接用JPA呢,就像使用java.util一样?
再再次提起老帖子
《RichDomainObject的架构设计中,是否可以抛弃DAO?》
http://pig345.javaeye.com/blog/79822

给domain对象注入session或者dao最常见的两个反面回答是:形成循环依赖。Domain对象无法脱离数据库存在。但是我并不完全认同这些说法。个人认为Ruby的ActiveRecord其实就是这么干的,而且用得还挺好。但是经过我做过这个实验,我相信,不用DAO,也可以活得挺好,甚至用起来比DAO还方便。


相信尝试过DomainModel的,都会有同感:
在当前的技术条件下,大多数Domain逻辑的实现 本身就是依赖持久化数据的,人为地硬说Domain不依赖持久层,就如同掩耳盗铃--自欺欺人而已,看看Rails里面(相对来说)漂亮干净的ActiveRecord就知道了,它根本就是基于数据库的。
另外,硬将DataAccess从Domain中分离出去,从而说Domain不依赖DAO,其实就是在开玩笑,这必将造成大部分领域逻辑泄露到DAO中或上窜到Service/Facade中,形成“贫血模型+事务脚本”。

从上边的观点看,根本无须顾虑程序代码上Domain层对Persistent层的依赖;
另外,
1)从实际出发,一个完整的企业应用,基本上都需要数据库参与;
2)再考虑到:有效的测试应该是尽量与实际运行环境相符的测试,也就是有数据库参与的测试;
因此,要Domain对象脱离数据库可供测试,基本上就是一个“空想”的优点!

如果只是为了解决测试方便性的问题,前面早有答案:使用内存数据库。
这比使用(花费不少时间自己编写的各种)MockDAO进行测试,要让人踏实多了,毕竟单元测试的环境跟实际运行环境更贴近了一步。
   
0 请登录后投票
时间:2008-05-11
同意你的说法。使用内存数据库,然后再用spring给domain对象注入一个generic的DAO。我上文提到的解决方案,其实那个RichSet就是一个generic DAO。而注入是通过hibernate实现的。异曲同工而已。也同意你对于脱离数据库“可测试性”的质疑。我也没有明确的例证可以说明其优点。不过,通过RichSet的隔离,至少使用数据库和不使用数据库的选择,交在了你的手上,而不是被框架给限定住了。另外RoR的Fixture让数据库相关的测试变得容易。但是Java中缺乏相因的设施,使得结合数据库的测试显得相对冗长。
其实Persistent就不是一层。。。持久化也压根不是逻辑。它只是Domain的一种存在形式。Domain可以在内存中也可以在数据库中,也可以部分在内存中部分在数据库中。
   
0 请登录后投票
时间:2008-05-11
taowen 写道
同意你的说法。使用内存数据库,然后再用spring给domain对象注入一个generic的DAO。我上文提到的解决方案,其实那个RichSet就是一个generic DAO。而注入是通过hibernate实现的。异曲同工而已。也同意你对于脱离数据库“可测试性”的质疑。我也没有明确的例证可以说明其优点。不过,通过RichSet的隔离,至少使用数据库和不使用数据库的选择,交在了你的手上,而不是被框架给限定住了。另外RoR的Fixture让数据库相关的测试变得容易。但是Java中缺乏相因的设施,使得结合数据库的测试显得相对冗长。
其实Persistent就不是一层。。。持久化也压根不是逻辑。它只是Domain的一种存在形式。Domain可以在内存中也可以在数据库中,也可以部分在内存中部分在数据库中。

其实我是建议直接使用JPA,毕竟已经是java的标准设施。
另外理论上Persistent应该是透明(无业务逻辑),但目前技术情况下,其实很多的JPQL/HQL里面确实包含了不少的Domain逻辑的判定,Domain使用JPA也能尽量将这些逻辑收集到DomainModel的内部。
   
0 请登录后投票
时间:2008-05-11
JPQL和HQL就不是持久化逻辑。他们是查询逻辑。查询逻辑是典型的Domain Model应该关心的东西。
   
0 请登录后投票
时间:2008-05-11
taowen 写道
JPQL和HQL就不是持久化逻辑。他们是查询逻辑。查询逻辑是典型的Domain Model应该关心的东西。

呵呵,也是。
那就更需要在Domain中使用JPA了。
   
0 请登录后投票
时间:2008-05-12
我是不太赞同Java采用Rich Domain Model的,起码Java的框架做不到Rails的ActiveRecord那样简洁,这不仅仅是语法差异造成的,也和Rails的部署运行方式有紧密的关系。

1、Rails的进程运行模式是每个进程持有一个永久连接,一直不释放。

由于Rails不需要释放连接,所以不存在数据库连接资源的清理问题。但是Java的每个线程最终要释放数据库连接,所以必须精心的设计和编码,确保资源得到正确顺序的释放。但是一旦考虑到一个数据库连接的范围内,要跨多个domain model的方法调用进行数据库访问,那么你如何确定连接释放的顺序和时间点?起码你不可能在domain model的方法调用内部进行close了,必须依赖外部的容器管理,比方说依赖Spring提供的资源管理能力,由Spring来确认最后一个方法调用结束之后来帮助你关闭数据库连接。正因为Java的domain model摆脱不掉外在容器的依赖,所以他没有办法做到ActiveRecord那么简洁。

2、Rails的事务管理机制是很粗糙的,不像Java的事务管理那么精细

Rails默认情况下是单步提交的数据库事务,如果你希望跨多个model的事务,则必须手工写代码来管理。当然用Java也可以手工管理,但是对于已经适应了由容器来提供声明式事务管理的程序员来说,能够接受在Web层手工写丑陋的Transaction代码来管理事务的方式吗?

3、Rails没有IoC,但是有open class和mixin

因为ruby的open class和mixin,所以Rails没有IoC并不是什么问题,domain之间的调用不需要依赖外部容器,单元测试也不需要依赖外部容器,但是Java没有open class和mixin,所以必须强调接口编程和IoC容器管理,但这样一来,事情就复杂了,你背着一个容器编程,必须受到容器的制约。

因为以上的三个原因,Java要实现类似ActiveRecord的rich domain model,就面临比Ruby困难的多的问题,处处要背着一个IoC框架,而且这还意味着你的domain model也应该由IoC框架来创建,否则IoC框架无法给你注入依赖关系。所以这个IoC具有很强的传染性,你必须把所有的依赖关系全部放在IoC的控制之下。但是偏偏你用IoC去管理domain model,特别是prototype的model却是一件非常复杂和困难的事情,尤其Spring框架更是如此。

因此我个人不看好Java的rich domain model,尤其是当你不能摆脱Spring/Hibernate依赖的情况下,无法真正实现rich domain。所以我更希望看到Java领域出现一些新的框架或者思路出来,不要老是Spring/Hibernate那一套。或者可以这样说,正是Spring/Hibernate导致了Java领域贫血模型的出现,如果没有超越Spring/Hibernate(EJB3/JPA也一样)的Java框架出现,是不可能rich domain的。
   
0 请登录后投票
论坛首页 Java版 领域模型

跳转论坛:
JavaEye推荐
    快速回复 引用上一条消息 (Alt+S)