锁定老帖子 主题:领域模型——想说爱你很难
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-30
呵呵,design by buzzword的一个最大的问题是,往往这个大牛说的与另一个大牛说的并不一致,甚至很多时候是矛盾的。这个时候,相信哪个大牛是颇伤脑筋的,当然小陶他们肯定会相信Martin的说法。
|
|
返回顶楼 | |
发表时间:2007-04-30
dlee 写道 在Spring+Hibernate的架构中实现领域模型,发生的主要变化是:
不再需要有DAO类,DAO类所做的持久化逻辑被放在了领域模型对象之中(我上面叫做“与持久对象相对应的业务对象”其实不准确,准确的叫法是“领域模型对象”)。用我上面的例子就是将持久化逻辑放在UserOperation类中,不能放在UserEntity类中,绝对不能让持久对象自己来做持久化。这种改变好像类的数量一减一增,似乎应该于以前数量相同。其实不然,与持久对象对应的领域模型对象类的数量会比DAO类更多。这个领域模型对象因为同时拥有业务方法和持久方法,所以它是跨业务层和持久层的,这与J2EE的分层设计有些矛盾。领域模型对象与DAO对象有一个主要的差别是它们是有状态的,因此它们是prototype,而DAO对象是无状态的singleton。 一个主要的问题就是,在Spring+Hibernate的架构中,通常不能直接将一个PO当作一个领域模型对象来使用,而应该保持它的尽量简单,需要另外创建一个位于Spring IoC中的与之对应的领域模型对象。保持PO尽量简单还有一个好处就是可以重用它的类设计,例如与PO类相同的类设计也可以用来作为Web层的Command对象,并且可以将PO作为DTO来使用,传递到Web层。而对于领域模型对象来说,通常不要直接当作DTO对象来传递。 我为何总是将讨论范围局限在基于Spring+Hibernate的架构中呢?因为我知道小陶他们做Java开发也是基于这个架构。脱离开这个架构讨论什么是完美的设计,对于他们来说意义不是很大。 太麻烦了,直接在业务层中进行领域对象的操作不可以么? GenericDaoDelegate extends HibernateSupport implements DaoDelegate{ save(Entity entity); update(Entity entity); ... } abstract AbstractService { public void setDaoDelegate(DaoDelegate daoDelegate); protected DaoDelegate getDaoDelegate(); ... } XxxServiceImpl extends AbstractService implements XxxService{ bussinessMethod(){ getDaoDelegate().save(someEntity); ... getDaoDelegate().update(anotherEntity); ... } } 这样,“通常不要直接当作DTO对象来传递”,就可以改为“特殊情况下可以使用DTO来传递包装领域对象”了。 |
|
返回顶楼 | |
发表时间:2007-04-30
dlee 写道 在Spring+Hibernate的架构中实现领域模型,发生的主要变化是:
不再需要有DAO类,DAO类所做的持久化逻辑被放在了领域模型对象之中(我上面叫做“与持久对象相对应的业务对象”其实不准确,准确的叫法是“领域模型对象”)。用我上面的例子就是将持久化逻辑放在UserOperation类中,不能放在UserEntity类中,绝对不能让持久对象自己来做持久化。这种改变好像类的数量一减一增,似乎应该于以前数量相同。其实不然,与持久对象对应的领域模型对象类的数量会比DAO类更多。这个领域模型对象因为同时拥有业务方法和持久方法,所以它是跨业务层和持久层的,这与J2EE的分层设计有些矛盾。领域模型对象与DAO对象有一个主要的差别是它们是有状态的,因此它们是prototype,而DAO对象是无状态的singleton。 一个主要的问题就是,在Spring+Hibernate的架构中,通常不能直接将一个PO当作一个领域模型对象来使用,而应该保持它的尽量简单,需要另外创建一个位于Spring IoC中的与之对应的领域模型对象。保持PO尽量简单还有一个好处就是可以重用它的类设计,例如与PO类相同的类设计也可以用来作为Web层的Command对象,并且可以将PO作为DTO来使用,传递到Web层。而对于领域模型对象来说,通常不要直接当作DTO对象来传递。 我为何总是将讨论范围局限在基于Spring+Hibernate的架构中呢?因为我知道小陶他们做Java开发也是基于这个架构。脱离开这个架构讨论什么是完美的设计,对于他们来说意义不是很大。 要想不用Spring+Hibernate,要说服客户很难。我现在.NET开发,讨论这些纯属业余爱好,主业是Office插件开发……在现有的分层结构,在Spring+Hibernate上,要有突破很难。 |
|
返回顶楼 | |
发表时间:2007-04-30
dlee 写道 呵呵,design by buzzword的一个最大的问题是,往往这个大牛说的与另一个大牛说的并不一致,甚至很多时候是矛盾的。这个时候,相信哪个大牛是颇伤脑筋的,当然小陶他们肯定会相信Martin的说法。
你是说DDD嘛?我觉得大牛们的意见挺一致的啊。只是在现有技术上实现起来有困难,而在RoR上却很容易做到了。所以才会有思考,才要去创造啊。 |
|
返回顶楼 | |
发表时间:2007-04-30
dovecat 写道 我挺同意dlee和robbin的观点.增加了J2EE分层的模糊性,
并且领域模型对象感觉太超重了. 似乎大家不同意领域模的原因有两个: 1,感觉领域模型太重。 2,领域模型模糊了逻辑层和持久层。 如果分析一下: “重”是什么意思? 代码太多,接口太多,职责太多(等),并而有之,或而有之。 1,代码很多。 如果业务对象如果继承PO,代码的量只跟你的业务逻辑复杂度有关, 不管你用DAO或其它的什么方法,都有那么多代码量。 2,接口太多。PO的接口都是自动维护的,不会混乱你的逻辑,也不会增加你维护量, 如果你仅用数量指标(或一般的code rule),我们很多代码都会超标, 一般一个类的最合适的函数个数(15个还是多少?), 我们很多PO的setter或getter本身就要要超过这个量,假设一个表20个字段,就会至少40个函数。 但我想不会有人感觉PO是重的,我只听到人们说它是苍白的。 Java的Statement本来接口就很多,可是PrepareStatement增加了那么多接口,依然继承Statement接口, 而CallableStatement依然提拔地继承了PrepareStatement。 所以接口重的衡量标准包括数量,但这不是一个重要的标准(虽然它是简单的),更重要的是职责,维护的量。 所以String依然可以有那么接口,而人们不说(或我没听人们抱怨过)String过重或复杂。 code rule指定检查接口函数的个数,就是希望提醒你注意接口的职责专一,不要太复杂,不要难于维护。 所以在开发中,只要职责专一,易于维护,便于使用,就完全可以忽略接口的数量指标。 3,职责。这个要看你从什么角度去衡量了。我认为一个继承PO的业务对象的职责还是很明确简单的,如果你忽略背后的PO职责, 即使把增大眼球把PO职责挑出来加起来,总的职责也是很简单的,因为PO的职责简单,单一,无需管理维护。 至于:领域模型模糊了逻辑层和持久层 Some people认为是J2EE的分层策略导致了Hibernate+Spring复杂或其它什么的, 另一方,不这样做,Some people又感觉到模糊了分层。好人难做啊! 用业务对象跟分层是对立的吗? PO在持久层,业务对象在逻辑层。 持久层仍是持久层,逻辑层仍是逻辑层。 不是可以照样分层设计,分层开发,分层实施吗?(或许你对此有异议) What's your matter? |
|
返回顶楼 | |
发表时间:2007-04-30
taowen 写道 你是说DDD嘛?我觉得大牛们的意见挺一致的啊。只是在现有技术上实现起来有困难,而在RoR上却很容易做到了。所以才会有思考,才要去创造啊。
你说的大牛是一些专门研究架构设计的人,例如Martin Fowler。还有一些人是更偏向于应用和实践的,例如Rod Johnson、Gavin King等等。其实Rod Johnson和Gavin King的很多设计观点都是不一致的(体现在Spring和JBoss Seam的差别上)。另外PoEAA这本书出来也有很多个年头了,我可以确信Rod Johnson熟读过这本书,因为在《J2EE without EJB》中他不只一次引用过这本书。但是为何Spring框架在2.0版推出之前,对于实现领域模型并没有提供很好的支持?为何会出现这种情况,我们需要做一些深入的讨论。当然我相信Rod Johnson肯定并不反对领域模型,因为Spring在2.0版中使用AspectJ来更好地支持基于领域模型的设计。但是这是否说明了在Spring+Hibernate的架构中,实现完美的领域模型设计存在着很大的困难? 我的回答是:Rod Johnson与Martin Fowler具有不同的设计哲学。你们读过《J2EE without EJB》等书就会明白,Spring框架的一个主要的设计目标就是为了更好地支持分层的设计(业务逻辑要与持久逻辑清晰地分离开),而Martin Fowler设计领域模型的目标并不是支持分层,而是得到更好的面向对象设计,这两个设计目标是存在着很大的差异的。并不是完全不相容,但是要在两方面都做到完美确实不太容易。 |
|
返回顶楼 | |
发表时间:2007-04-30
我如果基于Ruby on Rails做开发,我当然会采用领域模型的方式来做开发。领域模型也不是什么高不可攀的神奇玩艺,实际上对于做过很多企业应用的人来说,PoEAA这本书还是很容易读懂的。
不过在我看来,随着各种RIA技术的兴起(Ajax、Flex、WPF、Apollo),将来越来越多的人会将Web表现层完全前推到客户端来做,服务器端的角色转换成了一种Web服务提供者(类似于基于SOAP的Web Service中的服务接入点,但是主要采用轻量级的Web Remoting协议)。由于角色的改变,服务器不再大包大揽做完所有的事情,这个时候,传统的J2EE的分层设计(表现层、业务层、持久层)的重要性将会越来越显得不是那么突出。 |
|
返回顶楼 | |
发表时间:2007-04-30
lihy70 写道 dovecat 写道 我挺同意dlee和robbin的观点.增加了J2EE分层的模糊性,
并且领域模型对象感觉太超重了. 似乎大家不同意领域模的原因有两个: 1,感觉领域模型太重。 2,领域模型模糊了逻辑层和持久层。 如果分析一下: “重”是什么意思? 代码太多,接口太多,职责太多(等),并而有之,或而有之。 1,代码很多。 如果业务对象如果继承PO,代码的量只跟你的业务逻辑复杂度有关, 不管你用DAO或其它的什么方法,都有那么多代码量。 2,接口太多。PO的接口都是自动维护的,不会混乱你的逻辑,也不会增加你维护量, 如果你仅用数量指标(或一般的code rule),我们很多代码都会超标, 一般一个类的最合适的函数个数(15个还是多少?), 我们很多PO的setter或getter本身就要要超过这个量,假设一个表20个字段,就会至少40个函数。 但我想不会有人感觉PO是重的,我只听到人们说它是苍白的。 Java的Statement本来接口就很多,可是PrepareStatement增加了那么多接口,依然继承Statement接口, 而CallableStatement依然提拔地继承了PrepareStatement。 所以接口重的衡量标准包括数量,但这不是一个重要的标准(虽然它是简单的),更重要的是职责,维护的量。 所以String依然可以有那么接口,而人们不说(或我没听人们抱怨过)String过重或复杂。 code rule指定检查接口函数的个数,就是希望提醒你注意接口的职责专一,不要太复杂,不要难于维护。 所以我们在开发中,只要职责专一,易于维护,人们就完全可以忽略接口的数量指标。 3,职责。这个要看你从什么角度去衡量了。我认为一个继承PO的业务对象的职责还是很明确简单的,如果你忽略背后的PO职责, 即使把增大眼球把PO职责挑出来加起来,总的职责也是很简单的,因为PO的职责简单,单一,无需管理维护。 至于:领域模型模糊了逻辑层和持久层 Some people认为是J2EE的分层策略导致了Hibernate+Spring复杂或其它什么的, 另一方,不这样做,Some people又感觉到模糊了分层。好人难做啊! 用业务对象跟分层是对立的吗? PO在持久层,业务对象在逻辑层。 持久层仍是持久层,逻辑层仍是逻辑层。 不是可以照样分层设计,分层开发,分层实施吗?(或许你对此有异议) What's your matter? ...怎么觉得有点...唉~~ 你去看看without ejb吧. 大牛们已经说得很清楚了,我才疏学浅,说不清楚. 另外:建议你去看看robbin的关于领域模型的讨论. |
|
返回顶楼 | |
发表时间:2007-04-30
是的,这里以前robbin写的一些文章对我的启发也是很大的。我们不能脱离开某种具体的架构来谈完美的设计(因为你不可能自己重新写一个Spring或者Hibernate)。掉书袋我也会的,引经据典起来保证不比各位差。
|
|
返回顶楼 | |
发表时间:2007-04-30
感觉DDD对于复杂领域系统的开发还是很有用处的,理论上说和具体实现的语言关系不是太大吧。
其实代码量的多少并不能说明问题,关键是思路的清晰程度(这个当然和项目的人员学识有关,所以DDD强调一个学习型的组织)。 |
|
返回顶楼 | |