论坛首页 Java企业应用论坛

领域模型——想说爱你很难

浏览 20069 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-04-30  
呵呵,design by buzzword的一个最大的问题是,往往这个大牛说的与另一个大牛说的并不一致,甚至很多时候是矛盾的。这个时候,相信哪个大牛是颇伤脑筋的,当然小陶他们肯定会相信Martin的说法。
0 请登录后投票
   发表时间: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来传递包装领域对象”了。
0 请登录后投票
   发表时间: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上,要有突破很难。
0 请登录后投票
   发表时间:2007-04-30  
dlee 写道
呵呵,design by buzzword的一个最大的问题是,往往这个大牛说的与另一个大牛说的并不一致,甚至很多时候是矛盾的。这个时候,相信哪个大牛是颇伤脑筋的,当然小陶他们肯定会相信Martin的说法。

你是说DDD嘛?我觉得大牛们的意见挺一致的啊。只是在现有技术上实现起来有困难,而在RoR上却很容易做到了。所以才会有思考,才要去创造啊。
0 请登录后投票
   发表时间: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?







0 请登录后投票
   发表时间: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设计领域模型的目标并不是支持分层,而是得到更好的面向对象设计,这两个设计目标是存在着很大的差异的。并不是完全不相容,但是要在两方面都做到完美确实不太容易。
0 请登录后投票
   发表时间:2007-04-30  
我如果基于Ruby on Rails做开发,我当然会采用领域模型的方式来做开发。领域模型也不是什么高不可攀的神奇玩艺,实际上对于做过很多企业应用的人来说,PoEAA这本书还是很容易读懂的。

不过在我看来,随着各种RIA技术的兴起(Ajax、Flex、WPF、Apollo),将来越来越多的人会将Web表现层完全前推到客户端来做,服务器端的角色转换成了一种Web服务提供者(类似于基于SOAP的Web Service中的服务接入点,但是主要采用轻量级的Web Remoting协议)。由于角色的改变,服务器不再大包大揽做完所有的事情,这个时候,传统的J2EE的分层设计(表现层、业务层、持久层)的重要性将会越来越显得不是那么突出。
0 请登录后投票
   发表时间: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的关于领域模型的讨论.
0 请登录后投票
   发表时间:2007-04-30  
是的,这里以前robbin写的一些文章对我的启发也是很大的。我们不能脱离开某种具体的架构来谈完美的设计(因为你不可能自己重新写一个Spring或者Hibernate)。掉书袋我也会的,引经据典起来保证不比各位差。
0 请登录后投票
   发表时间:2007-04-30  
感觉DDD对于复杂领域系统的开发还是很有用处的,理论上说和具体实现的语言关系不是太大吧。
其实代码量的多少并不能说明问题,关键是思路的清晰程度(这个当然和项目的人员学识有关,所以DDD强调一个学习型的组织)。
0 请登录后投票
论坛首页 Java企业应用版

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