论坛首页 Java企业应用论坛

贫血/充血模型转贴+自己的想法

浏览 4815 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-24  

   Martin Fowler很早以前就写过一篇文章,题目叫"贫血模型"。文章里面批判贫血的领域模型是不够优雅、不够OO的,提倡使用充血的领域模型。在Java世界里这是一直争论的话题。到底什么是贫血什么是充血呢?

  贫血模型:是指领域对象里只有get和set方法,或者包含少量的CRUD方法,所有的业务逻辑都不包含在内而是放在Business Logic层。

      优点是系统的层次结构清楚,各层之间单向依赖,Client->(Business Facade)->Business Logic->Data Access(ADO.NET)。当然Business Logic是依赖Domain Object的。似乎现在流行的架构就是这样,当然层次还可以细分。

      该模型的缺点是不够面向对象,领域对象只是作为保存状态或者传递状态使用,所以就说只有数据没有行为的对象不是真正的对象。在Business Logic里面处理所有的业务逻辑,在POEAA(企业应用架构模式)一书中被称为Transaction Script模式。

  充血模型:层次结构和上面的差不多,不过大多业务逻辑和持久化放在Domain Object里面,Business Logic只是简单封装部分业务逻辑以及控制事务、权限等,这样层次结构就变成Client->(Business Facade)->Business Logic->Domain Object->Data Access。

       它的优点是面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。

       缺点是如何划分业务逻辑,什么样的逻辑应该放在Domain Object中,什么样的业务逻辑应该放在Business Logic中,这是很含糊的。即使划分好了业务逻辑,由于分散在Business Logic和Domain Object层中,不能更好的分模块开发。熟悉业务逻辑的开发人员需要渗透到Domain Logic中去,而在Domian Logic又包含了持久化,对于开发者来说这十分混乱。  其次,因为Business Logic要控制事务并且为上层提供一个统一的服务调用入口点,它就必须把在Domain Logic里实现的业务逻辑全部重新包装一遍,完全属于重复劳动。

   如果技术能够支持充血模型,那当然是最完美的解决方案。不过现在的.NET框架并没有ORM工具(不算上开源的NHibernate,Castle之类),没有ORM就没有透明的持久化支持,在Domain Object层会对Data Access层构成依赖,如果脱离了Data Access层,Domain Object的业务逻辑就无法进行单元测试,这也是很致命的。如果有像Spring的动态注入和Hibernate的透明持久化支持,那么充血模型还是能够实现的。

个人看了这篇文章以后感觉还是有种对充血模型的向往 因为一直以来也不知道是自己钻牛角尖还是什么的 对于业务层混乱复杂的业务方法 还是希望能让领域模型自己去处理这些问题 但是对于业务层的重复定义方法也是不可避免的 长远考虑领域模型重用的话还是有好处的(虽然不一定会再用到) 最终通过orm工具对领域模型的持久化感觉这种方式还是挺不错的

   发表时间:2007-12-24  
可是 领域模型 里的持久化都是自动的,我觉得这很危险

比如
  执行了一句: user.addRole(role)

我的原意是先加一个role到内存中,然后再在内存中做校验
但是 按领域模型 的常见模式,这个role会被自动放到数据库中,这并不是我想要的。
0 请登录后投票
   发表时间:2007-12-24  
zengcuoan 写道
可是 领域模型 里的持久化都是自动的,我觉得这很危险

比如
  执行了一句: user.addRole(role)

我的原意是先加一个role到内存中,然后再在内存中做校验
但是 按领域模型 的常见模式,这个role会被自动放到数据库中,这并不是我想要的。


我想是否可以在addRole当中实现校验逻辑
一般的话userDao.store(user) 这样操作将user持久到数据库吧
自动的话应该也会在方法中做合法性校验的
0 请登录后投票
   发表时间:2007-12-24  
ecsun 写道
采用贫血模型,还是充血模型,要根据项目团队的整体技术情况而定,如果一个项目团队里,大多是新手,那么使用充血模型,肯定会有一定的阻力,相反,如果团队成员大多是老鸟,那就很方便了

能有一个这样的团队,写代码一定会挺愉快的
至少设计一个合理的模型是一件很有成就感的事
毕竟的定义值对象挺乏味的 而在业务逻辑层看复杂的业务逻辑代码也挺头大
0 请登录后投票
   发表时间:2007-12-24  
假设我的业务就是加进来之后, 结合user 和 role的信息校验呢?


pitt_xu 写道
zengcuoan 写道
可是 领域模型 里的持久化都是自动的,我觉得这很危险

比如
  执行了一句: user.addRole(role)

我的原意是先加一个role到内存中,然后再在内存中做校验
但是 按领域模型 的常见模式,这个role会被自动放到数据库中,这并不是我想要的。


我想是否可以在addRole当中实现校验逻辑
一般的话userDao.store(user) 这样操作将user持久到数据库吧
自动的话应该也会在方法中做合法性校验的
0 请登录后投票
   发表时间:2007-12-24  
zengcuoan 写道
假设我的业务就是加进来之后, 结合user 和 role的信息校验呢?


pitt_xu 写道
zengcuoan 写道
可是 领域模型 里的持久化都是自动的,我觉得这很危险

比如
  执行了一句: user.addRole(role)

我的原意是先加一个role到内存中,然后再在内存中做校验
但是 按领域模型 的常见模式,这个role会被自动放到数据库中,这并不是我想要的。


我想是否可以在addRole当中实现校验逻辑
一般的话userDao.store(user) 这样操作将user持久到数据库吧
自动的话应该也会在方法中做合法性校验的


其实对于充血和贫血毕竟没必要太强求什么
对于实际应用来讲 我觉得领域模型对业务逻辑的封装 并不是能满足所有问题的 也可以在业务层做更多操作的 有很多好的经验可以借鉴的
0 请登录后投票
   发表时间:2007-12-24  

[quote="pitt_xu"][quote="ecsun"]采用贫血模型,还是充血模型,要根据项目团队的整体技术情况而定,如果一个项目团队里,大多是新手,那么使用充血模型,肯定会有一定的阻力,相反,如果团队成员大多是老鸟,那就很方便了[/quote] 能有一个这样的团队,写代码一定会挺愉快的 :) 至少设计一个合理的模型是一件很有成就感的事毕竟的定义值对象挺乏味的 而在业务逻辑层看复杂的业务逻辑代码也挺头大[/quote]

跟项目的复杂度关系更大些吧!自己感觉(没有任何数据支持)绝大多数项目90%用户请求都是挺简单的业务操作。就我接触到的Web系统,至少都分为Action-Sevice-Dao这样三层,很多方法已经是简单的代理而已,根本就不存在业务层很重的说法。充血模型在这样的系统中只会认为增加复杂度

0 请登录后投票
   发表时间:2007-12-24  
的确是这样的 CRUD为主的项目还是简单处理比较好
0 请登录后投票
   发表时间:2007-12-24  
但是在充血模型中,有些finder方法是不是应该定义成static的?
因为这些方法不是跟特定的Domain Object有关的,而是所有Domain Object有关。
这样的话,模型中将会充斥大量static的方法。
给Mock Object模式的应用带来了一定的难度。
0 请登录后投票
论坛首页 Java企业应用版

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