`
ansn001
  • 浏览: 94837 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

领域模型的概念:失血 贫血 充血 胀血

阅读更多

转自:http://blog.csdn.net/seakingwy/article/details/4556755,仅供学习

领域模型概念的最合拍的解释:

由此我们终于看出来概念是怎样被偷换的了,一个商业概念的抽象领域模型被一个Java持久化实体类替代了。但是我们应该看到,Martin批评的贫血的领域模型并不是Hibernate实体类,Martin指的贫血的领域模型实际上是缺乏丰富业务逻辑概念的领域抽象模型,这和Hibernate实体类完全是风牛马不相及的东西。而Hibernate实体类只是具体编码过程中,为了实现一个领域模型而编写的一组基于POJO的对象中的,完成领域模型某个特征的类。而这个领域模型完整的特征并不应该,也不可能由一个非常粗颗粒度的单类完成,而是由一组互相协作的类完成:即Hibernate的实体类保持领域模型的状态;DAO接口实现类完成领域模型的持久化操作;Spring Bean类完成领域模型的逻辑控制功能。

POJO指的就是非EJB那种重量级,高侵入性的组件模型,关于POJO的定义,你同样可以在Martin Fowler的bliki上面找到。

Spring的Bean是不是POJO? 是的! 
Hibernate的entity是不是POJO?是的! 
DAO接口是不是POJO?是的! 
EJB是不是POJO? 不是的!

我没有看过Martin的DDD,我按照自己的理解, POJO domain models指的就是轻量级的领域模型。何为轻量级? 把领域模型的各个特征,各个属性,各个逻辑都塞到一个class里面叫做轻量级吗?

我认为,Martin批评的贫血的领域模型是指只关注了领域模型持久化特征方面,而忽略了领域模型其他特征方面的模型,这样的模型是贫血的。因为这种模型只关注了模型在技术层面的外在表现,也就是说只关注了数据的存取操作,而忽视了模型蕴含的业务核心价值。

举例来说,我们编一个银行软件,如果你只关注了账户的增删改查,这叫做贫血!而实际上你应该关注的是账户的业务特征,而不是数据特征,你应该关注的是账号开立的业务,账户注销的业务,账号过户的业务等等,这才是领域模型。这种领域模型在一个单纯的技术实现层面来说,对于最简单的业务,你可能只是Account类的增删改查,但是对于复杂的业务来说,他就不单但是一个类,一个表的简单操作了,例如开立账户,你要收手续费,以及考察个人财务状况,那么此时你需要的就是一组协作的类。

Martin提到领域模型,意在强调我们应该关注软件的业务,关注行业知识的内在规律,并且把这种规律建模为领域模型,批评拿到一个软件,脑子里面光想到数据库增删改查的人。这和我们的Hibernate持久化类毫无关系!

我的看法是:一个抽象的领域模型具备多方面的特征,你需要用一组互相协作的类来完成它,每一个或者一组类承担这个领域模型的某个特征。例如某个领域模型,例如上面的账户,你需要一组Hibernate持久化类:包括Account类,User类,Finance类,一组SpringBean类,AccountManager,FinanceManager,一组DAO接口和实现类。由这些POJO的类互相协作来共同完成这个领域模型。如果你仅仅关注Account的增删改查,那就贫血了,而如果你关注了账户的业务规则,并且考虑一组互相协作的类去完成它,就不是贫血的。

 

如果用DDD思考,hibernate ORM仅仅是为领域模型服务的,ORM的职责是持久化领域模型。领域模型属于业务层,而ORM实现类(比如具体的仓库实现类)属于持久层。

 

 

一、 失血模型

失血模型请看 http://forum.javaeye.com/viewtopic.php?t=11712 
中列举的第一种模型,简单来说,就是domain object只有属性的getter/setter方法,没有任何业务逻辑。

二、贫血模型

贫血模型请看 http://forum.javaeye.com/viewtopic.php?t=11712 
中列举的第二种模型,简单来说,就是domain ojbect包含了不依赖于持久化的领域逻辑,而那些依赖持久化的领域逻辑被分离到Service层。

Service(业务逻辑,事务封装) --> DAO ---> domain object

这种模型的优点:

1、各层单向依赖,结构清楚,易于实现和维护

2、设计简单易行,底层模型非常稳定

这种模型的缺点:

1、domain object的部分比较紧密依赖的持久化domain logic被分离到Service层,显得不够OO

2、Service层过于厚重

三、充血模型

充血模型和第二种模型差不多,所不同的就是如何划分业务逻辑,即认为,绝大多业务逻辑都应该被放在domain object里面(包括持久化逻辑),而Service层应该是很薄的一层,仅仅封装事务和少量逻辑,不和DAO层打交道。 
Service(事务封装) ---> domain object <---> DAO

这种模型的优点:

1、更加符合OO的原则

2、Service层很薄,只充当Facade的角色,不和DAO打交道。

这种模型的缺点:

1、DAO和domain object形成了双向依赖,复杂的双向依赖会导致很多潜在的问题。

2、如何划分Service层逻辑和domain层逻辑是非常含混的,在实际项目中,由于设计和开发人员的水平差异,可能导致整个结构的混乱无序。

3、考虑到Service层的事务封装特性,Service层必须对所有的domain object的逻辑提供相应的事务封装方法,其结果就是Service完全重定义一遍所有的domain logic,非常烦琐,而且Service的事务化封装其意义就等于把OO的domain logic转换为过程的Service TransactionScript。该充血模型辛辛苦苦在domain层实现的OO在Service层又变成了过程式,对于Web层程序员的角度来看,和贫血模型没有什么区别了。

四、胀血模型

基于充血模型的第三个缺点,有同学提出,干脆取消Service层,只剩下domain object和DAO两层,在domain object的domain logic上面封装事务。

domain object(事务封装,业务逻辑) <---> DAO

似乎ruby on rails就是这种模型,他甚至把domain object和DAO都合并了。

该模型优点:

1、简化了分层

2、也算符合OO

该模型缺点:

1、很多不是domain logic的service逻辑也被强行放入domain object ,引起了domain ojbect模型的不稳定

2、domain object暴露给web层过多的信息,可能引起意想不到的副作用。

在这四种模型当中,失血模型和胀血模型应该是不被提倡的。而贫血模型和充血模型从技术上来说,都已经是可行的了。但是我个人仍然主张使用贫血模型。其理由:

1、参考充血模型第三个缺点,由于暴露给web层程序拿到的还是Service Transaction Script,对于web层程序员来说,底层OO意义丧失了。

2、参考充血模型第三个缺点,为了事务封装,Service层要给每个domain logic提供一个过程化封装,这对于编程来说,做了多余的工作,非常烦琐。

3、domain object和DAO的双向依赖在做大项目中,考虑到团队成员的水平差异,很容易引入不可预知的潜在bug。

4、如何划分domain logic和service logic的标准是不确定的,往往要根据个人经验,有些人就是觉得某个业务他更加贴近domain,也有人认为这个业务是贴近service的。由于划分标准的不确定性,带来的后果就是实际项目中会产生很多这样的争议和纠纷,不同的人会有不同的划分方法,最后就会造成整个项目的逻辑分层混乱。这不像贫血模型中我提出的按照是否依赖持久化进行划分,这种标准是非常确定的,不会引起争议,因此团队开发中,不会产生此类问题。

5、贫血模型的domain object确实不够rich,但是我们是做项目,不是做研究,好用就行了,管它是不是那么纯的OO呢?其实我不同意firebody认为的贫血模型在设计模型和实现代码中有很大跨越的说法。一个设计模型到实现的时候,你直接得到两个类:一个实体类,一个控制类就行了,没有什么跨越。

这边提到ruby on rails,属于胀血模型,因为它把domain object和DAO都合并了。

窃以为RoR是居于表模块+活动记录,与JAVA适合的情况有些不同。采用活动记录的架构,在持久化的时候,语法貌似更OO些,是直接obj.save()这样,而不是DAO,save(obj)

 

先说明一下概念:

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中,这是很含糊的。

虽然贫血模型的缺点很明显,但是由于设计起来相当简单所以目前很多项目还在采用这种模型,包括我做过的很多项目。

相对于贫血模型 充血模型对设计人员的要求较高,尤其在没有 O/R mapping的时候 O/RM的广泛流行使得充血模型成为另外一种选择.

那么O/RM时代怎样实现贫血模型呢.

实践中我们需要注意以下几点
1.Domain Object 应该是有状态的
2.Domain Object应该包含业务逻辑
3.Domain Object应该不包括持久化逻辑,即不直接依赖于O/R Mapping
4.避免重复代理简单的CRUD 把CRUD从传统的DAO中分离出来 有Delegate来做其余负责的数据操作

下面是我总结后画的一个概念图:

下面是一个简单的例子:

 

分享到:
评论

相关推荐

    失血贫血充血胀血模型.docx

    胀血模型是对充血模型的一种扩展,领域对象不仅包含业务逻辑,还可能包含基础设施相关的代码,如数据访问代码。这种模型可能导致对象过于庞大,不易维护。 优点: 1. 自包含:领域对象能自我处理所有事务,无需依赖...

    领域驱动设计案例-盒马实践

    领域模型可以分为失血模型、贫血模型和充血模型三种类型。 失血模型 失血模型是基于数据库的领域设计方式,它指的是使用 POJO 数据对象来存储业务数据。在失血模型中,业务逻辑是分散的,分布在多个地方。 贫血...

    论文研究 - 资源贫乏地区的产后贫血和产后遗漏出血

    背景:产后出血是全世界孕产妇死亡的主要原因,贫血是其间接原因之一。 分娩期间贫血会增加发生PPH的风险,甚至在中度PPH后仍可能导致产妇死亡。 未确诊的PPH和产后贫血增加了社区晚期孕妇死亡的风险。 这项研究的...

    产后失血性休克.ppt

    【产后失血性休克】是产科严重并发症之一,主要发生在分娩过程中或产后,由于大量出血导致血容量急剧减少,进而引发全身微循环障碍,表现为低血容量性休克。这种状况对母亲的生命安全构成严重威胁,因此,对产后失血...

    产后失血性休克诊治进展.ppt

    当发生产后失血性休克时,通常失血量已经达到了1000毫升甚至更多,这会导致血容量的急剧下降,进而引发休克。 休克的程度与临床表现密切相关。根据失血量和血压、脉搏等生理指标的变化,休克可分为以下几个阶段: ...

    论文研究 - 血栓弹力图在判断早期失血性休克患者凝血功能异常中的价值

    目的:通过血栓弹力图(TEG)检测早期失血性休克患者凝血功能的变化。 方法:对50例早期失血性休克并有手术指征的患者进行TEG检查。 将TEG参数与50名健康人进行比较。 观察到早期失血性休克患者的凝血和纤维蛋白溶解...

    上消化道出血诊治进展.ppt

    5. 血象变化:失血性贫血为正细胞正色素性,出血24小时内网织红细胞升高,持续升高意味着出血未止;出血后2-5小时白细胞计数可能升高,随后逐渐恢复正常。 【分类】: 急性上消化道出血主要分为非静脉曲张性出血和...

    输血知识考试题.doc

    输血知识是一个重要的医疗领域,涉及临床医学、血液学等多个学科。输血是临床上用于治疗贫血、重症感染、凝血机制障碍、急性出血等症状的重要手段。以下将详细阐述相关知识点: 1. 输血适应症:输血的主要适应症...

    论文研究 - 血红蛋白值与术中失血量估算之间的关联

    简介:估计术中失血率对预测输血或血液制品需求非常重要,对外科医生和麻醉师而言很重要。 对于各种结果以及缺乏在手术室开始输血的明确指标,必须评估失血量。 研究的目的是评估血红蛋白(Hb)值和出血估计率。 ...

    执业医师考试资料:血液系统(用心记住考点,必定能过!).pdf

    3. **类型**:合成不足(如再生障碍性贫血、缺铁性贫血、巨幼细胞性贫血)、破坏过多(溶血性贫血)、急性/慢性失血性贫血。 **缺铁性贫血**: 1. **铁代谢**:二价铁吸收,三价铁运输,二价铁被利用。维生素C有助...

    完美医学课程之贫血.ppt

    形态分类包括大细胞性贫血(如巨幼细胞性贫血)、正细胞性贫血(如急性失血性贫血、溶血性贫血)和小细胞低色素性贫血(如缺铁性贫血、铁粒幼细胞贫血、地中海贫血)。病因和发病机制分类则涉及红细胞生成减少(如...

    输血适应症知识.pdf

    输血是一种重要的医疗手段,常用于纠正贫血、预防出血或者治疗各类血液疾病。本文将详细介绍输血适应症,包括血液科和其他内科、外科的情况。 在血液科,输血的适应症依据不同疾病的特点: 1. 再生障碍性贫血:当...

    机能综合实验报告失血性休克.doc

    实验报告主要探讨了失血性休克的机制、治疗方法以及在动物模型中的观察。失血性休克是一种由于急性大量失血导致的有效循环血量急剧减少,进而引发微循环障碍和器官功能障碍的临床综合征。实验通过模拟失血情况,观察...

    2018年临床执业医师资格考试辅导课件《血液系统》贫血讲义.pdf

    根据病因和发病机制,贫血可归为红细胞生成减少(如再生障碍性贫血、营养性贫血)、红细胞破坏过多(如溶血性贫血)和丢失过多(如失血性贫血)三类。 贫血的临床表现多样,最常见的是疲劳、困倦和虚弱。皮肤黏膜...

    输血知识试题.docx

    全血:适用于严重贫血或大量失血。 - B. 洗涤红细胞:适用于对血浆成分过敏的患者。 - C. 血小板制剂:用于治疗或预防血小板减少导致的出血。 - D. 血清蛋白:主要用于补充血浆蛋白,提升胶体渗透压。 - E. ...

    贫血诊断与治疗学习教案.pptx

    贫血的诊断通常涉及全面的临床评估,包括病史询问、体格检查、实验室检查(如血常规、网织红细胞计数、血清铁、铁饱和度、叶酸、维生素B12水平等)。治疗贫血的目标是找出并治疗根本原因,同时补充缺失的造血物质或...

    血液透析患者贫血的管理.ppt

    【血液透析患者贫血的管理】是针对慢性肾脏病(CKD)患者,特别是进行血液透析的患者,如何有效管理和治疗贫血问题的专业讲座或教材。贫血是CKD患者常见的并发症,随着肾功能的恶化,贫血的发生率逐渐增加。本资料...

    贫血的诊断思路.pptx

    实验室检查通常包括全血细胞计数、血涂片、网织红细胞计数、骨髓活检、铁代谢指标、溶血指标、遗传学检测等,以确定贫血类型和病因。治疗贫血的目标是针对病因进行干预,补充缺失的造血原料,改善骨髓功能,控制溶血...

Global site tag (gtag.js) - Google Analytics