锁定老帖子 主题:一个简单例子:贫血模型or领域模型
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-09-19
2004年那会儿上过javaeye,那会儿就看见robbin们讨论贫血充血了,
我觉得贫血和充血的两个概念很好,因为一说贫血或者充血我们就知道你说的是什么意思, 这两者是相对的但是不是水火不容的,那个方便用哪个嘛,先写的贫血代码可以重构成充血,觉得不方便的又可以转回来,他们是手段不是目的,没有高下之分没有正宗之分。 |
|
返回顶楼 | |
发表时间:2009-09-22
很多时候想充血都不一定是你充得了的,涉及多个领域对象的操作我看你能把代码充成啥样;再说了,还有很多时候一味充血一点好处都没有,比如说一个pojo由多个人来负责写他的行为,都充在一个文件里怎么操作,人说你可以搞继承嘛...。
我觉得这个非要把贫血吃成充血的思维,是由大家用OO硬套Domain Model造成的。在论坛上看了不少帖子,很多人的理解就是Domain Model=Domain Object=pojos,这样一来,领域中的行为和操作只能屈服于某个对象的淫威之下,忽视甚至无视XXXService很好地反映了领域逻辑并且是领域逻辑实现的一部分也就是必然的了。干掉xxxservice那那些逻辑怎么办呢?只能硬塞到pojo里面去了。对于这种思维我想说:你打算什么时候把领域中工作流的逻辑也塞到pojo里? 我这样说充血,并不意味着我喜欢贫血,充血有时候能减少xxxUtil之类的数量呢,正如我在上贴所说的,我不觉得这两者之间没什么矛盾, |
|
返回顶楼 | |
发表时间:2009-09-25
最后修改:2009-09-25
想问个问题
假如需要获得20个Cust账户到一个Map里,领域模型该如何做?? 这个Map作为项目唯一的一个实例,做个Singleton; 是不是这样写: instanceMap=new Cucst().listMap(20); 会不会造成new Cust()冗余呢? |
|
返回顶楼 | |
发表时间:2009-09-27
根本不是冗余的问题,把listCustomers设计为customer的一个方法,你不觉得别扭么。。。
不要试图将所有和Customer相关的逻辑都放到Customer中去。 C_J 写道 想问个问题
假如需要获得20个Cust账户到一个Map里,领域模型该如何做?? 这个Map作为项目唯一的一个实例,做个Singleton; 是不是这样写: instanceMap=new Cucst().listMap(20); 会不会造成new Cust()冗余呢? |
|
返回顶楼 | |
发表时间:2009-09-27
我就是觉得别扭才提出了那个问题;
所以这里又牵涉的另一个决策问题,就是到底哪些方法放到模型里面去? 其他行为又被安置到哪里呢? 不还是得封装出一个类似DAO的层面么? |
|
返回顶楼 | |
发表时间:2009-09-28
C_J 写道 我就是觉得别扭才提出了那个问题;
所以这里又牵涉的另一个决策问题,就是到底哪些方法放到模型里面去? 其他行为又被安置到哪里呢? 不还是得封装出一个类似DAO的层面么? 建议这样来理解:“模型里面”不仅仅是Java的那个pojo,xxxService也是模型的一部分。 |
|
返回顶楼 | |
发表时间:2009-09-28
终归还是没有解决部分xxxService放置的问题...
放到领域?放入DAO?或者放入Service层??? 所以领域模型 我觉得还是值得深思的... 也许贫血的领域模型也许更适合实际情况... |
|
返回顶楼 | |
发表时间:2009-09-28
C_J 写道 终归还是没有解决部分xxxService放置的问题...
放到领域?放入DAO?或者放入Service层??? 所以领域模型 我觉得还是值得深思的... 也许贫血的领域模型也许更适合实际情况... 想啥呢,本来就是领域的一部分, |
|
返回顶楼 | |
发表时间:2009-09-29
timshaw9791 写道 C_J 写道 终归还是没有解决部分xxxService放置的问题...
放到领域?放入DAO?或者放入Service层??? 所以领域模型 我觉得还是值得深思的... 也许贫血的领域模型也许更适合实际情况... 想啥呢,本来就是领域的一部分, 恩,对领域模型理解还是有点偏差~ |
|
返回顶楼 | |
发表时间:2009-10-19
lifethinker 写道
领域模型
优缺点
其优点是:
其缺点是:
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里面,是要好好考虑的. 有些问题请教一下:
|
|
返回顶楼 | |