论坛首页 Java企业应用论坛

领域模型的价值与困境

浏览 44095 次
该帖已经被评为精华帖
作者 正文
   发表时间:2008-12-01  
我觉得Dao层确实不好。虽然提供了访问数据库的接口,但是在实践中,对数据不变量的保证往往都游离与service中,所以我现在的做法就是用DDD中的repository来取代dao,但是repository与dao不同的是:repository要负责保证领域模型数据的不变量(配合一定的规则类),这样一部分的不变量保证由聚合根来完成,另外的不变量则有仓库来完成。
0 请登录后投票
   发表时间:2008-12-01   最后修改:2008-12-01
robbin 写道
我来说几句吧:

所以最终我对这个问题的总结就是:

一、只要技术框架能够实现,尽量使用领域模型

二、无论Java还是Ruby,必须消灭DAO和TransactionScript

三、领域模型不必All-in-One,Java可以分割为 1个entity bean和几个business bean,而Ruby可以分割为1个model和几个mixin的module。





比较同意 robbin 的观点。

的确是技术或框架,限制了领域模型的应用。

当J2EE 起步时, 主流的是EJB规范. 它的不好之处就是为了Container或Server的考虑,强行在规范中分为了 EntityBean,SessionBean, 并且作为业务bean的SessionBean,除了Bean实现类,还有两个怪异的Remote接口,Home接口。也就是说 Sun 等大佬们,一开始就违背了 领域模型和OO的思想来设计 EJB 规范。 而后,又提出一些J2EE设计模式, 如DAO, Facade等推荐大家使用.

那时大家都懵懵懂懂,自然将Sun 的规范看作圣经。自然三层架构,以及 DO + DAO + BO 模式一直作为一个设计准则被大家采用。 而Spring等后来的轻量版,也没摆脱这一规程。

   所以个人认为,如果说领域模型未能成功发展,主要还是EJB规范, J2EE 服务器, Spring框架 等技术限制导致的。

   领域模型要想推广成功,没有一个像 Gavin King 这样的大师或者 某一个大厂商的技术框架,领域模型规范,App Server来支持,恐怕很难落到实处。



2 请登录后投票
   发表时间:2008-12-02  
有个折中的办法,像pojos in action里面一样把dao的接口当成实体方法的参数,dao的职责和实体方法的需求有关,可以做到充血模型
0 请登录后投票
   发表时间:2008-12-02  
还有,硬要充血,spirng2的@Configurable是可以实现对实体的IOC注入的
0 请登录后投票
   发表时间:2008-12-02   最后修改:2008-12-02
robbin 写道
我来说几句吧:

第一、DAO层和TransactionScript层是邪恶的!

我们在2004年一直跨度到2007年讨论来讨论去,其实都有一个隐含的前提条件:你的领域模型终究无法脱离对DAO层的依赖,以及需要TransactionScript层的包裹。而这样一来,领域模型的通用性、可移植性、业务逻辑的表达能力基本全部丧失,沦为框架限制下的奴隶。

而我们看看现在Java领域的技术进步,JPA已经普及,EJB3的隐含事务管理,甚至连Spring也可以简化成@Transactional,现在已经是我们可以去掉DAO和TransactionScript的时代了。


第二、Seam在消除了DAO层和TransactionScript以后,领域模型的感觉已经呼之欲出


这个不用多说,大家自己去看Seam文档好了。我唯一想强调的是entity bean和business bean分开有没有必要性,我的看法是有必要!这还是和Java本身语言的限制有关系:

1、Java语法表达能力有限,entity bean又不得不弄一大堆getter/setter方法,都放在一个class里面,代码的可阅读性非常差

2、business bean的很多业务逻辑方法需要容器环境,不像Rails的model可以直接mixin进来

3、Java做为目前最主流的工业语言,开发团队都是大规模编码协作的,你都放在一个class里面,团队协作会遇到很大的麻烦(事实上RoR现在也有这样的问题,但是RoR开发效率高,往往不需要那么大规模的开发团队)

3、领域模型不同类别的业务逻辑可以很容易的分到几个不同的business bean里面,这样对团队协作的好处很大。


第三、不考虑框架限制,All-in-One的领域模型好不好?


比方说RoR的model就是All-in-One的,但是一旦出现可以抽象出来,比较通用的业务逻辑,我们还是会把这些逻辑抽出来,单独实现,然后再mixin回去。


所以最终我对这个问题的总结就是:

一、只要技术框架能够实现,尽量使用领域模型

二、无论Java还是Ruby,必须消灭DAO和TransactionScript

三、领域模型不必All-in-One,Java可以分割为 1个entity bean和几个business bean,而Ruby可以分割为1个model和几个mixin的module。




非常认同.
DAO消灭的原因是O/R Mapping的成熟,它已没有存在的必要.他出现的目的只是为技术服务--技术层面上SQL与Business的解耦.随着技术的成熟,他已没有存在的必要了.更准备的说是DAO担当的功能被替代掉了.
Java中的entity bean和business bean必需要分开,他们代表着一静一动
我认为要分的理由是(和robbin的会有不同,主要是不同的角度去看): OO的本质还是在按人的理解现实世界方式去组织软件世界中的数据与指令, 很明显现实世界的石头是不会动的,马路也是不会动的,他们就是Java中的entity bean.
如果只有Rich domain, 那么, 我们生活的世界就是动画世界了, 石头会主动打人,马路会自动拐弯, 转去生活在这种世界会有什么问题呢, 走路时要小心下一步会不会踩空,爬山时要担心石头会不会主动打人,你会突然发现要考虑好多意外因素啊,很麻烦,会把人累疯.这样的软件世界也会出类似情况.
0 请登录后投票
   发表时间:2008-12-03  
需知自然地未必是最佳的,就好像计算机总有一天可以征服自然语言,但你敢把它用在阿波罗登月上吗?如果敢的话应该是在心电感应这种操控技术发展成熟之后
0 请登录后投票
   发表时间:2008-12-03  
taowen 写道
但是一旦有了DistributionDao,就不一样了。
distributionDao.save(new Distribution(somePublication));

哈哈,啥控制都管不了我了吧。很多时候Dao就是这么无法无天的。如果说domain model是数据的防火墙,那么dao就是顶级黑客。由于Entity不能注入等实现和宗教信仰上的限制,往往导致了service对DAO的滥用,就会造成上面这样的by-pass domain model的情况。



这里我有个疑问,希望taowen兄解惑一下。如果distribute()方法中直接访问数据库,把新产生的Distribution保存到数据库中,这样就避免了在service中直接引用distributionDao,这样做有什么问题吗?

另外为什么service中会存在 distributionDao.save(new Distribution(somePublication));  这样的代码呢,这明显违反了系统的设计原则。虽然我们不能保证系统中所有的dao都是被领域模型包装起来的,但是起码应该能保证已经被领域模型包装起来的dao,就决不允许有其他service对其引用。这样的设计原则我们已经坚持了很久,也没有发现什么问题。反之,肆意破坏这个原则,会导致本来应该封装到领域模型中的逻辑泄露到service中,进而导致下面这个问题:

taowen 写道
数据和行为距离很远。造成了不容易理解数据含义,因为你光看entity压根不知道它会被怎么用。漏掉一些servie中细微的用法,就可能会造成很大的bug。
同时这也更加让可重用的逻辑更难被发现,从一定程度上鼓励了大家各自发明,一份逻辑写n遍,还n遍都不一样。。。




0 请登录后投票
   发表时间:2008-12-05  
我越来越觉得灵活是如此的邪恶,以至于人们接二连三的发明各种各样的实现方式。效率似乎在决定采用哪种策略中不知不觉被丢失了。

也许python之道能给人一点启示,解决一个问题,只需要一种方式。Java的领域模型从一定角度来看似乎是对开发人员有这样的假设,假设开发人员丝毫不懂领域知识,假设开发人员总是想恶搞,而通过代码机制来约束开发人员不该做的事情。

在尝到如此讲究的建模方式的种种好处和各式苦头之后,感觉还是实用是王道。解决得了实际问题是王道,Java被一些自作聪明的所谓架构设计师搞得庞杂无比后,越来越像浓妆艳抹的女人,让人忍不住怀念她曾经单纯时的美。

一点牢骚,还望各路神仙手下留情
1 请登录后投票
   发表时间:2008-12-08  
有人说DAO可以屏蔽数据库的底层实现细节,让程序代码能够在不同数据库之间切换,这是很难做到的,一般情况下DAO只是出于不重复造轮子来封装一些数据库级别的操作,并且业务开发人员不必去操作RS,SQLException这样的数据库级别对象而已,至于屏蔽数据库差异,但凡是某个接口可以输入整句sql,开发人员就有可能传入只有某个数据库才能运行的语句,所以除非能让开发人员彻底不需要写sql(Hibernate这样),屏蔽数据库差异是不可能的.
0 请登录后投票
   发表时间:2008-12-10  
bloodrate 写道
有人说DAO可以屏蔽数据库的底层实现细节,让程序代码能够在不同数据库之间切换,这是很难做到的,一般情况下DAO只是出于不重复造轮子来封装一些数据库级别的操作,并且业务开发人员不必去操作RS,SQLException这样的数据库级别对象而已,至于屏蔽数据库差异,但凡是某个接口可以输入整句sql,开发人员就有可能传入只有某个数据库才能运行的语句,所以除非能让开发人员彻底不需要写sql(Hibernate这样),屏蔽数据库差异是不可能的.

治愈SQL和关系数据库照成的隔阂几乎不可能,SQL本质就是输出一个2维表,想在一个2维表里面表示一个树形的东西,冗余是不可避免的,想不冗余就要多次往返了,多次往返的代价要在可以接受的范围,要么就寄望强大的缓存,强大的索引系统(lucene)。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics