DDD领域驱动设计给我们指出统一建模统一语言的方向,从辨识角度提出区分实体和值对象的方法,如果说DDD只是给出了领域建模的方向,也就是WHAT部分,那么,对象设计:角色、责任和协作"(Object Design: Roles, Responsibilities, and Collaborations)则更详细地从HOW角度提出如何从职责和协作中发现并丰富对象
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设计模型,特别是其中的行为模式,很多方面和职责协作是相通的,如果有命令、事件、调用、访问、通讯、观察、监视等行为发生,我们就认为有协作发生,反之亦然。,DDD领域驱动设计给我们指出统一建模统一语言的方向,从辨识角度提出区分实体和值对象的方法,如果说DDD只是给出了领域建模的方向,也就是WHAT部分,那么,对象设计:角色、责任和协作"(Object Design: Roles, Responsibilities, and Collaborations)则更详细地从HOW角度提出如何从职责和协作中发现并丰富对象。
总之,如果你非常熟悉GoF设计模型,特别是其中的行为模式,很多方面和职责协作是相通的,如果有命令、事件、调用、访问、通讯、观察、监视等行为发生,我们就认为有协作发生,反之亦然。