论坛首页 Java企业应用论坛

一个简单例子:贫血模型or领域模型

浏览 77068 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-09-19  
2004年那会儿上过javaeye,那会儿就看见robbin们讨论贫血充血了,
我觉得贫血和充血的两个概念很好,因为一说贫血或者充血我们就知道你说的是什么意思,
这两者是相对的但是不是水火不容的,那个方便用哪个嘛,先写的贫血代码可以重构成充血,觉得不方便的又可以转回来,他们是手段不是目的,没有高下之分没有正宗之分。
0 请登录后投票
   发表时间:2009-09-22  
很多时候想充血都不一定是你充得了的,涉及多个领域对象的操作我看你能把代码充成啥样;再说了,还有很多时候一味充血一点好处都没有,比如说一个pojo由多个人来负责写他的行为,都充在一个文件里怎么操作,人说你可以搞继承嘛...。

我觉得这个非要把贫血吃成充血的思维,是由大家用OO硬套Domain Model造成的。在论坛上看了不少帖子,很多人的理解就是Domain Model=Domain Object=pojos,这样一来,领域中的行为和操作只能屈服于某个对象的淫威之下,忽视甚至无视XXXService很好地反映了领域逻辑并且是领域逻辑实现的一部分也就是必然的了。干掉xxxservice那那些逻辑怎么办呢?只能硬塞到pojo里面去了。对于这种思维我想说:你打算什么时候把领域中工作流的逻辑也塞到pojo里?

我这样说充血,并不意味着我喜欢贫血,充血有时候能减少xxxUtil之类的数量呢,正如我在上贴所说的,我不觉得这两者之间没什么矛盾,
0 请登录后投票
   发表时间:2009-09-25   最后修改:2009-09-25
想问个问题

假如需要获得20个Cust账户到一个Map里,领域模型该如何做??

这个Map作为项目唯一的一个实例,做个Singleton;

是不是这样写:

instanceMap=new Cucst().listMap(20);





会不会造成new Cust()冗余呢?
0 请登录后投票
   发表时间:2009-09-27  
根本不是冗余的问题,把listCustomers设计为customer的一个方法,你不觉得别扭么。。。
不要试图将所有和Customer相关的逻辑都放到Customer中去。
C_J 写道
想问个问题

假如需要获得20个Cust账户到一个Map里,领域模型该如何做??

这个Map作为项目唯一的一个实例,做个Singleton;

是不是这样写:

instanceMap=new Cucst().listMap(20);





会不会造成new Cust()冗余呢?

0 请登录后投票
   发表时间:2009-09-27  
我就是觉得别扭才提出了那个问题;

所以这里又牵涉的另一个决策问题,就是到底哪些方法放到模型里面去?


其他行为又被安置到哪里呢? 不还是得封装出一个类似DAO的层面么?
0 请登录后投票
   发表时间:2009-09-28  
C_J 写道
我就是觉得别扭才提出了那个问题;

所以这里又牵涉的另一个决策问题,就是到底哪些方法放到模型里面去?


其他行为又被安置到哪里呢? 不还是得封装出一个类似DAO的层面么?


建议这样来理解:“模型里面”不仅仅是Java的那个pojo,xxxService也是模型的一部分。

0 请登录后投票
   发表时间:2009-09-28  
终归还是没有解决部分xxxService放置的问题...

放到领域?放入DAO?或者放入Service层???

所以领域模型 我觉得还是值得深思的...

也许贫血的领域模型也许更适合实际情况...
0 请登录后投票
   发表时间:2009-09-28  
C_J 写道
终归还是没有解决部分xxxService放置的问题...

放到领域?放入DAO?或者放入Service层???

所以领域模型 我觉得还是值得深思的...

也许贫血的领域模型也许更适合实际情况...

想啥呢,本来就是领域的一部分,
0 请登录后投票
   发表时间:2009-09-29  
timshaw9791 写道
C_J 写道
终归还是没有解决部分xxxService放置的问题...

放到领域?放入DAO?或者放入Service层???

所以领域模型 我觉得还是值得深思的...

也许贫血的领域模型也许更适合实际情况...

想啥呢,本来就是领域的一部分,


恩,对领域模型理解还是有点偏差~
0 请登录后投票
   发表时间:2009-10-19  
lifethinker 写道

 

领域模型

 

 

 

优缺点

 

其优点是:

  1. 领域模型采用OO设计,通过将职责分配到相应的模型对象或Service,可以很好的组织业务逻辑,当业务变得复杂时,领域模型显出巨大的优势。
  2. 当需要多个UI接口时,领域模型可以重用,并且业务逻辑只在领域层中出现,这使得很容易对多个UI接口保持业务逻辑的一致(从领域模型的分层图可以看得更清楚)。

其缺点是:

  1. 对程序员的要求较高,初学者对这种将职责分配到多个协作对象中的方式感到极不适应。
  2. 领域驱动建模要求对领域模型完整而透彻的了解,只给出一个用例的实现步骤是无法得到领域模型的,这需要和领域专家的充分讨论。错误的领域模型对项目的危害非常之大,而实现一个好的领域模型非常困难。
  3. 对于简单的软件,使用领域模型,显得有些杀鸡用牛刀了。

 

 

 

Repository接口属于领域层

 

可能有人会将Repository接口,相当于贫血模型中的DAO接口,归于基础设施层,毕竟在贫血模型中DAO是和它的实现放在一起。这就涉及Repository 接口到底和谁比较密切?应该和domain层比较密切,因为Repository接口是由domain层来定义的。用TCP/IP来类比,网际层支持标准以太网、令牌环等网络接口,支持接口是在网际层中定义的,没有在网际层定义的网络接口是不能被网际层访问的。那么为什么在贫血模型中DAO的接口没有放在model包中,这是因为贫血模型中DAO的接口是由service来定义的,但是为什么DAO接口也没有放在service包中,我无法解释,按照我的观点DAO接口放在service包中要更好一些,将DAO接口放在dao包或许有名称上对应的考虑。对于领域模型,将Repository接口放入infrastructure包中会引入包的循环依赖,Repository依赖Domain,Domain依赖Repository。然而对于贫血模型,将DAO接口放入dao包中则不会引入包循环依赖,只有service对DAO和model的依赖,而没有反方向的依赖,这也导致service包很不稳定,service又正是放置业务逻辑的地方。JDepend这个工具可以检测包的依赖关系。

 

 

 

DAO到底有没有必要?

 

贫血模型中的DAO或领域模型中的Repository到底有没有必要?有人认为DAO或者说Repository是充血模型的大敌,对此我无论如何也不赞同。DAO或Repository是负责持久化逻辑的,如果取消掉DAO或Repository,将持久化逻辑直接写入到model对象中,势必造成model对象承担不必要的职责。虽然现在的ORM框架已经做得很好了,持久化逻辑还是需要大量的代码,持久化逻辑的掺入会使model中的业务逻辑变得模糊。允许去掉DAO的一个必要条件就是Java的的持久化框架必须足够先进,持久化逻辑的引入不会干扰业务逻辑,我认为这在很长一段时间内将无法做到。在rails中能够将DAO去掉的原因就是rail中实现持久化逻辑的代码很简洁直观,这也与ruby的表达能力强有关系。DAO的另外一个好处隔离数据库,这可以支持多个数据库,甚至可以支持文件存储。基于DAO的这些优点,我认为,即使将来Java的持久化框架做得足够优秀,使用DAO将持久化逻辑从业务逻辑中分离开来还是十分必要的,况且它们本身就应该分离。

 

 

 

领域模型确实一个比较好的概念, 特别是解决贫血模型里面service越来越重的业务逻辑,以及业务的重用. 但是确实对于使用原来贫血模型的人是个考验,其中一个问题就是业务的划分, 究竟哪些业务该放在model里面,哪些该放在service里面,是要好好考虑的.

有些问题请教一下:

  1. 按我的理解,model对象是可以调用repository里面的操作的, model对象应该是不可以调用其它model对象(如果调用会造成service被架空)
  2. 看到你列的领域模型的目录结构, domain里面并没有dao, 你的意思是dao这层不需要, 由repository直接调用infrastructure? dao 有封装数据库操作的作用, 我觉得看起来还是要的
  3. 领域模型里面的facade也有作用么,看起来它也只是调用一下domain里面service啊
0 请登录后投票
论坛首页 Java企业应用版

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