重析业务逻辑架构模式,浅浅滴

     记得大约在一年前,我曾写过相关议题的文章,叫做业务逻辑架构模式(事务脚本,表模块,活动记录,领域模型)再谈业务逻辑架构模式(事务脚本,表模块,活动记录,领域模型),经过这一年多做项目的沉淀,特别是最近十天来,我又仔细研读了<Microsoft.Net企业级应用架构计设>这本书,并上了iteye论坛相阅了相关贴子,发现以前的很多认识是不全面的,甚至是错误的,相关的概念与认识也有了进一步的明确与清淅.觉得甚有必要将最新的一些想法与反思记录下来,达到总结提高的目的.

 

      一.总论

      首先来看一张图:

 

 


      我的第一篇文章里曾出现过类似的图,但是现在若干细节上有所不同,下面一一来分析

 

      二.事务脚本

      这是一种最直接的业务架构模式,他将后台所有的模块(包括我们常说的Dao,Server,Entity,BL层等)整合在了一起形成一个层,使用的是最彻底的用例驱动----UI上有什么样的操作, 这一层就有什么方法.没有专门表达数据结构的类,所有对数据的操作都是直接的Sql方式.

 

      三.表模块

      虽然这种模式还是把所有的模块都整合成一个层,但是已经开始有了对数据基本的抽象了.在.net里,就是将数据库抽象成一个DataSet,将其中的每一张表抽象成一个DataTable.对数据的操作,就是对这些DataSet与DataTable的操作.一般来讲,使用这种模式的BL层的类内置一个DataSet或DataTable类型的成员或属性来装载数据,所以这种BL类一般表达的是对整张表或者是对数据集合的操作,但是因为DataSet或DataTable在表达数据方面是弱类型的,所以在表模块里是没有办法使用强类型的对象的.

 

      四.活动记录

      虽然这种模式还是把所有的模块都整合成一个层,但是与表模块相比,有两个值得注意的地方.

      1.在这种模式里,对于数据的抽象就更进一步了----通过对象来表达数据,也就是对数据的强类型抽象.

      2.一般来讲,使用这种模式的BL层的类,其属性就是数据库的列,一个对象就是数据库中的一行数据,所以其表达的操作是对数据行的操作.这也是与表模块模式最大的不同.

      在.net里,ActiveRecord框架就专门表达这种模式的框架,通过其底层封装的类库与代码生成工具, 能够很快生成与这种模式相适应的.net代码.

 

      五.领域模型

      这种模型是我这篇文章的重点.在领域模型里,通过对BL层的分解来达到复用与灵活.按照iteye资深会员robbin的观点(我也基本赞同),特将此模型按实现方式的不同再分为以下4小类:

      1.失血模型

      在这种模型里,有一个Entity类来抽象数据,其只有属性,没有方法来表达业务,还有一个EntityManage类来表达领域逻辑与业务逻辑.

      2.贫血模型

      在这种模型里,有一个Entity类来抽象数据,用属性表达数据,还有少许不依赖其它层次与技术的领域逻辑,用属性或方法表达.还有一个EntityManage类来表达依赖其它层次与技术的领域逻辑和业务逻辑.

      3.充血模型

      在这种模型里,有一个Entity类来抽象数据,用属性表达数据,还有大部份的领域逻辑与业务逻辑,用属性或方法表达.还有一个EntityManage类,仅仅封装事务和少量逻辑,主要起一个外观的作用.

      4.胀血模型

      这种模型与活动记录比较像,就是不再分层,而是把所有的层全都放在一起.

 

      在这四种模型当中,失血与胀血是应该不被提倡的.胀血模型与活动记录差不多,而把其中所有的逻辑拿到另外一个类中后就成了失血模型,两个都走了极端.剩下的两个模型:贫血模型与充血模型,就要视情况而定了.在我看来,我更推崇贫血的领域.如下图所示:

 

 

 

      先来解释两个名词:领域逻辑与业务逻辑.所谓领域逻辑,就是领域本身特有的,不依赖具体执行环境的逻辑.比如一份合同,有签订时间与有效期,那么计算过期时间就是他的领域逻辑.业务逻辑,则是与领域相关,依赖特定执行环境的逻辑.比如合同订金,是依赖于合同的种类与金额大小的,有的15%,有的3%,有的签订合同当场就要缴纳,有的则有其它的条件与时限.

      首先看领域层.领域层分为两部份:领域对象与领域逻辑.领域对象就是领域层的静态部份,通常表现为属性,在大部份的程序里他的大部份都会与数据库的列一一对应.领域逻辑是领域层的动态部份,是那些不依赖其它层次与技术的领域逻辑.在上图中可以看到我把领域层与表现层衔接了起来,表示领域层的对象也可作为DTO传到表现层上面去.

      然后再看服务层.包括了依赖其它层次与技术的领域逻辑和业务逻辑.服务层是系统的核心,系统中的各个层次与各种技术都要与他发生交互.在上图中,上承表现层,下调领域层,通过IOC注入执行环境,通过AOP分离系统逻辑,通过ORM透明持久化,通过MSDTC定义事务边界等等.

 

      在这里,有几点需要重点说明

      A 在我看来,领域层是可以复用的,是面向对象的,为了达到这个目的,就一定要保证领域层的"纯洁" .所谓"纯洁",就是指:a) 领域层不能依赖任务具体的执行环境.比如我现在在做国土业务,政府在卖地的时候,会发几样凭证,其中一个叫<建设用地批准书>,一个叫<供地合同>.全国各地都是这么发的,但是发证的顺序与科室却有所不同,有的是M部门发A,N部门发B,有的是Q部门AB一起发.为了使这两个领域模型重用,就必需不能包含以上发证逻辑;b) 领域层不能依赖于具体技术实现.比如现在用的比较多的是NH,但是我建议还是不要让领域层依赖于他.万一重用后的环境用的是EF,就麻烦了.有时,为了简化程序层次,也可作为DTO传到表现层上面去.

      B 在我看来,服务层是用例驱动的,是面向过程的,大部份情况下是无法实现复用的.为了帮助领域层保持"纯洁",服务层就不得不"不纯洁"了.就如同上面所说的,上承表现层,下调领域层,通过IOC注入执行环境,通过AOP分离系统逻辑,通过ORM透明持久化,通过MSDTC定义事务边界等等.系统中所有的一切,都在服务层形成了交汇.

      C 在Asp.Net WebForm环境中,有时简单起见,会把页面的CodeBehined代码与Server层合并.这样可以减少系统的层次.不过如果系统比较大,比较复杂,还是不要这么干.

      D 真正好的领域模型是重构出来的.一个行业的信息化是一个从不稳定到稳定的过程,一个业务的理解也是由浅入深的过程.在一开始,可能我们不确定这是不是个核心业务,业务的具体表现形式也可能多变,这时可能我们会把逻辑写到CodeBehined里;经过一段时间的沉淀后,可能觉得这个业务较为通用,表现也趋于稳定,这时我们就可能会把其重构到Server层里;最后我们发现其实这个业务经过更高级别的抽象后有其不变的地方,这时我们就会考虑将其技术细节剥离后放入领域模型.

      E 在我看来,复杂查询,报表与统计在本质上不是面向对象的,而是面向数据的,且业务非常不稳定,那么他们也就不必通过领域模型来完成.而是直接从Server层连接到DB来完成相关功能.

      F 领域驱动设计与领域模型虽然经常配合起来使用,但其实是两个层面上的东西.领域驱动设计,强调的是在业务分析过程中,以业务为核心进行分析建模,是一种分析方法论;而领域模型则是一种强调在技术实现中,以业务为核心,是一种技术实践的方法论.

 

      在我看来,充血模型会提高领域层的耦合性,在业务上耦合了特定业务场景,在技术上耦合了特定技术选型,所以我更倾向于使用贫血模型.

      其实以上文章只是我在结合了自己的理解后炒的冷饭,早在5,6年前,iteye论坛就已经组织讨论过相关话题,02年POEAA就出版了,想到自己的相关技术水平还只停留在别人10年前的水平,感觉很是惭愧.

      以上的贫血模型,其实只能比较好的解决中小规模的项目.一旦项目复杂度上到一定的程度后,此模型仍然运作的不是很理想.下一步,就是要进一步的研究近些年出现的相关知识,如DCI,四色模型,CQRS等.争取从更高层次完成对系统的拆分,实现系统更理想的复用!在这方面,园子里已经有两位先行者了:dax.net与netfocus.有时候,能站在先驱与巨人的肩膀上学习,真是件很幸福的事啊~~~

 

      引用的文章

      一.关于领域模型

      谈一谈贫血的Domain Logic问题

      总结一下最近关于domain object以及相关的讨论

      看看Rod Johnson怎么讲Domain Object

      再次小结领域模型的种种观点

      二.贫血VS充血

      从贫血领域模型到丰富领域模型

      为什么java里不能把域对象和DAO合并,rails里面就可以?

      domain model的延伸讨论

      对Robbin《domain model的延伸讨论(重新编辑) 》一文质疑

      Rich Domain Model In Java ORM

      关于领域模型、DAO的疑问??

      Domain Object贫血vs富血(DDD)和spring roo到ruby的扯淡

      三.其它

      Domain injection with AOP

      命令和查询责任分离(CQRS)架构模式 读后疑惑

      领域模型的价值与困境

      再论领域模型的困境

      运用四色建模法进行领域分析

posted @ 2011-11-20 01:14  永远的阿哲  阅读(1984)  评论(4编辑  收藏  举报