如何从职责和协作中发现丰富对象?

10-02-09 banq
              

DDD领域驱动设计给我们指出统一建模统一语言的方向,从辨识角度提出区分实体和值对象的方法,如果说DDD只是给出了领域建模的方向,也就是WHAT部分,那么,对象设计:角色、责任和协作"(Object Design: Roles, Responsibilities, and Collaborations)则更详细地从HOW角度提出如何从职责和协作中发现并丰富对象。

从程序员角度来看:职责和协作是对象方法行为的两种表现形式,对象内部行为称为职责;对象之间互动行为称为协作。但是职责和协作其实是对象内部行为或相互调用的来源,我们看到的代码往往是行为结果,为什么对象中有这个方法行为,而不是那个对象行为,为什么对象之间要有这种调用,为什么不能放在一个对象中实现?

Martin Fowler曾经总结“重构”写了一本书,书中罗列了很多重构方法,比如extract method,现在Eclipse工具重构refactor都有这些重构方法,但是在何种场景下使用这些重构方法?为什么要将方法在对象之间迁移?如何能够界定哪个方法行为和哪个对象更接近?如果我们从分析建模开始就引入职责和协作设计,一切都迎刃而解。

一个对象通过不同职责能够扮演多个角色,从而实现不同业务场景情况下的业务功能,职责一旦复杂比较大,就会被切分,分配到两个以上对象中,就形成了对象之间的协作。协作模型是描述“how” 和 “when” 和 “with whom.” 的动态行为,

软件的交互协作使用如下Speak for Me软件描述:

假设用户是盲人或不能讲话,躺在医院病床上,她被囚禁了,不能用任何方式联系,除了眨眨她的眼睛,表“是”或“否”。她向Speak for Me发出字母消息,软件替代讲话,用一个小的传感器监视她的眼睛眨,用来进行字母的选择,并且能够根据各自场景规则算法猜测语句,供其选择。她可以通过眨眼发出命令,比如眨眼发出”RE”读取邮件,发出 “CH”寻求帮助。

该用户是表达者,软件是服务者,表达者驱动软件为之服务,服务者隐藏了具体实现细节。如果我们隐藏了某个对象如何工作的实现细节,我们就可以在不影响使用者的情况下灵活地改变具体实现方式。

使用协作模型可以帮助我们分清WHAT和HOW,实现声明式设计,达到DSM或DSL层面。

如果使用一群互相适合的对象在一起协作工作,支持一个大的职责,这是一个好的设计方式,DDD提出的聚合对象群也是这样一个目的,两者是一致的,下一步就是继续关注对象是如何协作的,设计消息(方法)执行步骤以及他们的参数和返回值。

通常有下面几个职责和协作模式:

1.信息拥有者模型,当一个对象是信息拥有者,它的职责是知道这些信息,不应该期望和其他对象协作获得信息。

有时信息拥有者的职责将他们数据持久化(明确提出了对象自己实现自己保存到数据库是对象职责)

信息是否被缓存,如果修改如何更新,这是如何协作的?(明确提出对象自己负责自己缓存是对象职责)。

比如:在线银行的界面,接受交易数据,然后传给服务的提供者,这个服务将其保存在“交易记录”这个对象中。

这里仅有的协作者就是“交易记录”对象自己使用持久层技术服务把自己保存到硬盘上。

2.组织结构模型。类似UML中常提到的聚合和组合,专门有一个结构组织者(父对象)来管理它的部件,比如Car和发动机 方向盘就是聚合关系,Car负责管理部件间的结构,这类似部门经理管理部门一样,和Facade模式非常相似。

除此之外,结构组织者(父对象)还要关心结构本身是否需要持久化?谁负责做这些持久化?这些对象是否被一个结构掌握访问?结构是否组织隐藏对象之间关系?或者将其暴露给协作?其他对象是否知道这种组织并访问?

这些提问就可以帮助你实现父子对象之间方法行为的分配,实现封装和开放的OO设计原则。总之,一般是父对象知道自己子对象,就要使用结构模型。

另外,还有其他模型,比如:服务提供者模型,这类似于DDD中的服务模型,还有控制者模型和协作者模型:控制者能区分事情,决定采取行动;协作者通常是让它做什么就做什么,很少做决定,有一个领导和部下,方向战略和战术的关系。

协作者模型和前面的结构者模型是有区别的,协作者模型侧重管理一群工作者的行为,而结构者管理一群对象,表达一种它们之间的高聚合视图。类似GoF设计模型中行为模式和结构模式的区别。

比如:当用户在编辑一个文档时,选择保存,软件在保存到文件之前必须做几种决策,即将保存的格式 (HTML, text, PDF, etc.)、是否取一个文件名?监视用户行为动作的对象将直接响应这些决策,或在协作者之间分享决策。

本人以前在批判面向数据库设计软件时,就以文档编辑为例子,你只要发出保存命令,而不必关心是如何保存的,者实际又是一个WHAT(什么命令)和HOW(如何执行命令)的关注分离。

此外,还有接口模型,如何定义接口,接口分用户接口 内部接口和外部接口,接口封装了职责和协作,因此,提倡面向接口编程不是只是使用接口语法就可以,也不只是使用面向接口的框架就可以,这些都是表面的,真正的是用接口表达对象的职责和协作。

对象设计:角色、责任和协作"(Object Design: Roles, Responsibilities, and Collaborations)一书还提出了分层的职责,如下图;DDD提出了分层架构,但是层的职责功能以及之间如何交互是什么没有详细定义。

总之,如果你非常熟悉GoF设计模型,特别是其中的行为模式,很多方面和职责协作是相通的,如果有命令、事件、调用、访问、通讯、观察、监视等行为发生,我们就认为有协作发生,反之亦然。

[该贴被banq于2010-02-09 17:25修改过]


              

17
atester
2010-02-22 11:24

个人感觉,越来越像agent模式了

agent模式已被证明为实现复杂系统的有效模式,是oo的一个分支,现在有一些书在写如何用Agent模式进行agent建模、agent通讯、多agent系统及智能agent系统。

完全可以这样认为:丰富对象就是一个简化了的agent,极复杂的丰富对象,也就相当于一个智能的agent。

[该贴被atester于2010-02-22 11:33修改过]

banq
2010-02-22 11:50

2010年02月22日 11:24 "atester"的内容
agent模式已被证明为实现复杂系统的有效模式,是OO的一个分支,现在有一些书在写如何用Agent模式进行agent建模、agent通讯、多agent系统及智能agent系统。

不会吧,我搜索en.wikipedia.org和google,都没有发现很多agent模式体系介绍,这又是一个“中国式”的自我发现吧。

agent模式应该等同于gof模式中proxy模式,如果你把面向对象的切分,增加中间者,都看成是代理,是可以将小小代理模式进行泛化,可惜没有必要,创造新名词只能会使简单事情复杂化。

大家能不能多做点复杂事情简单化的事情,比如OO世界中已经有职责模式Responsibilities,你就别再发明一个Agent模式来再说明?这不是增加复杂性了,大家都说Responsibilities不是更容易让人理解吗?模式就是共见,而不是个见,另外,引用指向别人会说明你没有主见吗?这不是中国创造的方向,呵呵。

随便说话,不针对楼上啊。

[该贴被banq于2010-02-22 11:53修改过]

atester
2010-02-22 14:07

这方面中文书很多了,而且有些书是做为研究生教材出版的,随便找了一个链结:

http://www.toopoo.com/book/tushu/121-07984-9.html

既然是丰富,那就必定是比简单的复杂了。而模式,通常是指出一个解决这个“丰富”问题的通常办法,这个办法能解决的问题越多,模式就会越复杂,但是却可以把这一个模式套用解决N多问题的方法。对于模式,这个简与繁是无法避免的。如果不针对具体应用,也不可能说明哪个更好,哪个不好....

atester
2010-02-22 14:17

我也感觉有不妥的地方,实际上,凭感觉,我觉得书中介绍的agent,其复杂性甚至达到了spring和ejb这样的框架的水平。

而模式,通常都不会是这么复杂的。

也许只是书上叫"agent模式",而凭经验,我感觉这是一个框架级的东西。

2Go 1 2 下一页