闲侃Domain Logic Patterns

最近总是在思考Domain Logic Patterns的几种形式,这也让我不得不从先哲们的书中探寻答案。看了下martin 的Patterns of Enterprise Application Architecture,感觉略微明白了点事情。

在Domain Logic Patterns这个问题上面,martin归结了三种主要形式。Transaction Script、Domain Model、Table Module。

java里面的名词真是很多,让人摸不着头脑。简单说吧,domain logic pattern是关于构建什么样的domain model并操作他们来完成business logic的几种模式。

我也不打算重复martin对这个问题的精辟解释了,具体的可以看看他的那个书,国内也有好多朋友早就关注过这个问题了,可以看看透明思考的blog。我只想形象化的来说说这个问题。于是我写了下面这个假象的情景。

老板让我办一个全由机器人作为演员的戏剧。这些机器人是有自己运行状态的比如在舞台什么位置,要说些什么台词;不仅如此,这些机器人还可以定义和别的机器人存在的复杂关系,比如有个机器人是自己的妻子,还有一群机器人是自己的孩子。

=======================================
martin : 从oo角度看,你这戏剧就相当于一组要完成的business logic了。这些机器人就相当于domain model。机器人的属性就相当于domain model里面的属性了。机器人和别的机器人的关系就相当于entity 的relationship
=======================================

老板还发话了,这戏剧得全自动录像,要把机器人走到什么位置,做了什么动作,说了什么台词都记录下来。幸好机器人外面提供了一个叫DAO的接口可以把机器人内部状态保存起来,可是这DAO接口可是什么事情也不做的,我们得自己按照这个接口的规范自己把功能实现了!据机器人制造商说是为了方便,你可以自己来用不同方法保存机器人状态,比如保存在文件里面啦,保存在数据库里面啦,等等。制造商说了,这个接口不仅机器人自己可以调用,控制机器的人也可以调用!是非常强大和透明的!我自己嘀咕着:废话,你啥事情都没做当然强大了,还不得我自己完成那。

=======================================
martin: 恩,制造商的做法还是相当不错的,提供了个接口,那样也方便了用户的扩展,机器人内部或者操纵的人使用起来也比较透明化。我们就把它叫做DAO层吧
=======================================

我感觉最适合的是采用一个数据库来记录这些信息,不过老板只提供我一个关系型的数据库,我认识到问题的严重了,把对象式的数据存储到关系型的数据库可有点麻烦,我还是比较懒的,工夫不负有心人,终于让我发现了一个叫hibernate的组件,这东西居然十分好使,只要几下就把DAO那个接口给实现了。

======================================
martin: 你就别惊讶了,DAO对hibernate也只是个瘦包装罢了,如果你不用考虑扩展的话,你可以直接把hibernate做在机器人里面,不过这样还是有点不那么优雅。
======================================

为了让这些机器人自动演出戏剧,没有脚本怎么行!于是我就为了剧情开始写脚本。这些机器人还是很笨的,从A点走到B点这样的行动都得我亲自在脚本里面说明,我脚本里面从A点到B点这个行动我这么写的
A点出发-方位45度行走3米-方位30度行走5米-到达B点。
我每次都要在脚本里面重复上面的东西是多么让人痛苦的事情!我梦想:要是只给机器人从A-B的指令,他自己能走过去是多么的棒!!!那样我的脚本只要这么写了
从A走到B。
那把这样的A到B走路的功能做个脚本放到机器人里面,我委托机器人完成不就可以了?于是我找来制造商的技术支持mm,我给她叙述了我的需求,她说我们公司是有这样可编程的机器人的,可是你们公司采购的都是不可编程的机器人。

我的天啊!把所有应该机器人内部处理的功能都让我在脚本里面处理!会死人的呀!我怀着万般无奈,还是把一份冗长的脚本做完了。不过虽然冗长,但是还是比较简单直观的,我也不用去考虑机器人内部有些什么预置的功能,反正一步步按我脚本走就是了。

=======================================
martin: 我真是很了解你的痛苦,其实你的痛苦就是现在很流行的Transaction Script做法,这种做法把属于domian model固有的方法剥离了,放到script里面了。这样造成的就是我说的贫血的domain model,而在你看来就是这样的没有编程功能的木头机器人。这是我们极力应该避免的。
=======================================

由于演出还算成功,在第二次表演的时候,我极力要求老板全部换成可编程的机器人,并且威胁他说,不换我就走人。老板鉴于先前的机器人话剧取得了很大成功,还是满足了我的要求,于是我乐呵呵的到机器人公司mm那里订购了一批可编程机器人。

可是带来的问题是我该给这些机器人内部做些什么功能呢?哪些功能的确是属于机器人固有的,哪些功能是我需要在脚本里面说明的,这问题思考起来真是头痛。

=======================================
martin: 这就是domain model这种模式的难点了,构建一个优美紧凑的domain model可不是一件容易的事情啊。不过你还是要为你的行动感到自豪,你现在在赋予木头人思维,让他真正成为一个机器人,所以还是坚持下去吧,虽然有时候你会发现自己的机器人功能会很庞大,但是不要担心,我们总是有办法来使这个模型变的更好,孩子你还是去看看这本书吧《Domain-Driven Design》
=======================================

由于我最终构建了一个非常好的模型,所以我的脚本写起来相当简单而灵活,而且一旦需要演别的话剧,这些机器人内部的有些方法是可以复用的,为我做新的脚本减轻很多负担,我觉得使用这样一种机器人确实是非常好的。

=======================================
martin: 孩子,你终于得到回报了,其实你以前使用的Transaction Script模式是面向过程的而不是面向对象的,从表象上看,你确实拥有很多model,但是这些model仅仅是domain data struct,而不是domain object,因为按照object的定义,object需要有数据和操作的。我们长久以来为之奋斗的面向对象的概念,在Transaction Script这里遭受了重创。我们确实该回到domain model这种形式,让我们把本该属于domain model的方法从service layer剥离出来,按回原位。其实存在这样一种refactor方法,让你从Transaction Script回到domain model。这个就自己去寻找吧。
=======================================

写这个文章我参考了几份文档
Patterns of Enterprise Application Architecture
By Martin Fowler, David Rice, Matthew Foemmel, Edward Hieatt, Robert Mee, Randy Stafford

AnemicDomainModel
http://martinfowler.com/bliki/AnemicDomainModel.html

透明思考Blog中关于这个的讨论
http://gigix.blogdriver.com/gigix/166013.html

在此做个广告,我也常在自己的blog里面有些胡思乱想的东西,欢迎大家批评指正。
我的blog才建不久,http://napoleon.blogdriver.com/napoleon/index.html
新手看看也许会更适合,因为我自己也刚入门不久,所以可能有些问题会有相同的困惑。可以探讨探讨。

也可以通过电子邮件与我联系 napoleonn@21cn.com

非常不错,对初学者很有益处,Java编程关键在于OO思想的培养,这个过程只有一个字:难。

所以,我一直疑问,为什么国内计算机高等教育不首先从OO开始,而是从过程开始,导致大量毕业后的程序员要经过痛苦的自我裂变,真是误人子弟阿。