关于领域模型的设计问题,JavaEye已经组织过n多次大规模讨论,几乎每过一段时期就会出现一次。最近出现了一个新的趋势,Craig Walls在自己的blog上面写一篇文章,介绍如何使用Spring2.0和AspectJ的新特性给domain object注入DAO依赖,即如何实现post-instantiation,请见:
http://jroller.com/page/habuma?entry=spring_2_0_vs_the
与此同时,ajoo也给出了nuts的post-instantiation方案,请见:
http://www.iteye.com/display/ajoo/Dependency+Injection+For+Rich+Domain+Model
因此,从技术手段来上说,对于Spring/Hibernate架构,Martin的Rich domin model变得可行了,那么让我们看看究竟有哪些领域模型,以及他们的优缺点:
一、失血模型
失血模型请看
http://forum.iteye.com/viewtopic.php?t=11712 中列举的第一种模型,简单来说,就是domain object只有属性的getter/setter方法,没有任何业务逻辑。
二、贫血模型
贫血模型请看
http://forum.iteye.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
http://robbin.iteye.com/blog/17579?page=1#comments
这种模型的优点:
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认为的贫血模型在设计模型和实现代码中有很大跨越的说法。一个设计模型到实现的时候,你直接得到两个类:一个实体类,一个控制类就行了,没有什么跨越。
关于领域模型的问题,限于时间原因,暂时不能展开详谈,待有空,写篇更加详细的文章。
分享到:
相关推荐
领域驱动设计入门以及实践,如何用领域驱动设计来做
DDD领域模型设计方案
3.2.1 设计领域模型 3.2.2 定义项目聚合 3.2.3 定义聚合边界 3.2.4 设计仓储 3.2.5 编写单元测试 3.3 解决方案 3.3.1 project类 3.3.2 实现仓储 3.3.3 实现服务类 3.3.4 实现项目信息视图模型 3.3.5 实现...
什么是领域(Domain)? 我们所做的软件系统的目的都是来解决一系列问题,例如...通常我们说,要成为一个领域的专家,必须要在这个领域深入研究很多年才行,只有这样才会遇到非常多的该领域的问题,积累了丰富的经验。
领域模型设计详细举例.pdf领域模型设计详细举例.pdf领域模型设计详细举例.pdf领域模型设计详细举例.pdf领域模型设计详细举例.pdf领域模型设计详细举例.pdf
如何设计架构-分层和组织领域模型 层(layer)这个概念在计算机领域是非常了不得的一个概念。计算机本身就体现了一种层的概念:系统调用层、设备驱动层、操作系统层、CPU指令集。每个层都负责自己的职责。 要组织...
领域驱动设计的简略设计步骤 ,领域驱动模型的设计实例
领域模型最近代码实现 领域模型最近代码实现 领域模型最近代码实现
领域模型使开发人员可以表达丰富的软件功能需求,由此实现的软件可以满足用户真正的需要,因此被公认为是软件设计的关键所在,其重要性显而易见。但讲述如何将领域模型用于软件开发过程的优秀实用资料却不多见。本书...
基于UML的医院信息系统领域模型设计我在网上找到的资源希望对大家有所帮助
DDD则不同:它像是更小粒度的迭代设计,它的最小单元是领域模型(Domain Model),所谓领域模型就是能够精确反映领域中某一知识元素的载体,这种知识的获取需要通过与领域专家(Domain Expert)进行频繁的沟通才能将专业...
收集来自主流的DDD开发理论知识培训课程,包括: 领域驱动设计简介 领域通用语言 领域驱动设计的构造块 领域驱动设计编程实践 CQRS架构 模型驱动开发
通过业务领域模型驱动设计, 关于降低设计复杂性的好书。
微服务背景下的架构方案,领域驱动设计与模型驱动开发
如何设计和构建初始的领域模型 如何实现“持久化无关” 如何为领域模型构建仓储框架 将TDD应用到领域模型的技能 如何应用模型—视图—视图模型模式 如何构建客户端会员管理系统 如何将客户系统和服务器同步 《领域...
lec-5 领域模型 DomainModel.ppt
在互联网产品追求快速迭代上线的今天,需求多变,业务逻辑和流程繁琐冗长,代码很难维护的场景下,开发该如何在效率和优雅中平衡,今天跟大家交流“领域驱动设计”在复杂业务中的实战心得。
领域模型驱动设计(DDD)之领域模型驱动设计(DDD)之模型提炼模型提炼
Eric Evans所著的《领域驱动设计》(Domain-Driven Design:通常简称为“DDD”)一书可以说是经典中的经典,虽然“领域”的概念早就存在,但是直到这本书的出现,才让人们真正开始认真审视软件的构建,相信你看了这...