分析模式 - 责任模式

分析模式 - 责任模式

概念模型比较难说清楚,概要性描述:
最直观的例子是组织结构,上级组织与下层组织之间的关系,从具体层面讲是一种所属关系,Martin将它抽象为一种责任关系。人和组织之间的所属关系是责任关系;管理者与部署之间的关系是责任关系;部门与部门负责人、经理之间的关系是责任关系。书中Martin将这种关系进一步泛化到更广的范围,个人认为没有多少实用价值,因为具体应用中对业务概念不能太泛化,否则将显得很牵强,即软件结构中的某些部位、接口责任过重。另外注意书中一开始就提到模型中的所有概念都是面向接口,而非面向实现,因此对象类型与派生类型之间并不一定是继承关系、各种派生类型也不必是在同一个数据库表中,仅仅是实现某个接口而已
在抽象层面就有一些抽象概念
Party: 参与者,责任关系中任何一方都属于参与者
Accountability: 责任关系,从数据模型来理解就是两个或多个参与者之间的对应关系,以及相关属性
Commissioner: 委托方,从具体例子来讲就是参与者中的所有者(owner)、管理者等
Responsible: 责任方,从具体例子来讲就是参与者中的下层组织、被管理者等

原书中Martin使用对象模型来表述,尤其是使用了非标准的类UML表示(Odell表示法,即ERStudio采用的方法),所以比较难理解。另外的原因就是抽象层次比较高,具体环境中的设计变数很多,对象模型和数据模型之间可能差距较大,对象间职责作用关系有点繁琐,这也是造成难以理解的原因之一
很多大型数据处理型系统中这方面都设计的非常灵活,看起来也很直观,没有概念的干扰没有对象模型的变幻莫测,因此主要使用数据模型的方式做个笔记

pattern 1:
最普通的设计就是采用简单的Adjacency List Model,例如组织结构的设计
数据模型:                                                  对象模型:
                               
贫血模型中可以使用int ParentId关联上级组织,向前走一点可以使用Organization1 Parent,还可以使用一个IList<Organization1> Children

对于小型组织、公司,这个设计基本能满足要求。情况稍微复杂一些,例如大型生产制造型企业,有工厂生产组织结构、分销渠道组织结构、集团总部行政管理的组织结构,在矩阵型组织中不同的组织结构之间形成矩阵型交叉,例如产品线、项目等,与功能型组织结构就会交叉,这对组织结构的设计要求会比较高

pattern 2:
基于上面的例子考虑稍复杂一点的情况,例如有两个组织结构需要管理,一个销售组织结构,一个生产组织结构,简单的设计可以这样
数据模型:                                                        对象模型:
                       
这是将两棵树存储在一起,每个组织结构可能只属于销售组织结构、生产组织结构,也可能同时属于这两个组织结构,对每一棵树的维护和使用,基本类似pattern 1

pattern 3:
1. 如果有更多的组织结构,采用pattern 2就很难维护;从图论的观点来看,pattern 1和pattern 2都将树节点(node)和树的边(edge,即父子关联关系)存储在一起了。将这两个数据分开存储,就具备进一步扩展的基础了。即将组织对象(节点)和组织结构树型关系(边)分开存储
2. 考虑下面这种组织结构关系:
   
集团总部的下面只能是区域总部,区域总部下面只能是分公司,即用组织(节点)来构造树型结构时,需要遵循一定的规则,因此将组织(节点)类型独立提取出来,并在类型上面建立规则。目的是能够方便的添加新的组织(节点)类型,使用规则配置而不需要修改代码,就能建立新的组织结构
3. 不同组织结构同样使用类型区分(组织类型、组织结构类型是两种概念,前者是节点类型,后者是树型结构的类型),每种类型对应一棵树型结构,添加一种新的组织结构图同样只需要添加新的组织结构类型,并进行配置

数据模型:
   
Organization3Type: 组织类型,例如区域总部、分公司、销售点
Organization3StructureType: 组织结构类型,例如销售组织、生产组织
Organization3: 具体的组织(节点)对象
Organization3Structure: 树型结构
Organization3StructureRule: 规则表,例如组织(节点)对象组成树型结构的规则

数据示例:
   
   
说明:
1. 对象模型的设计方案比较灵活,不再列出来,以免该死的UML反而产生误解
2. Organization3StructureRule的职责只在于限制Organization3Structure,它描述、约束了树型结构的大致形状。如果要修改规则表中的规则数据,确保Organization3Structure中已经存在的数据符合新的规则是一件麻烦事情
   可以这样理解,业务对象是Organization3和Organization3Structure,其它数据、对象只是一些设计构造,目的是便于业务扩展。Martin将其总结为知识层级(knowlege level)和操作层级(operational level),个人不太认同,因为没有必要制造这些概念
3. 添加新的组织类型、新的组织结构类型,配置组织结构树的构成规则,然后就可以维护多种不同类型的组织结构,单从组织结构维护这个功能来看,这已经是一种可配置的设计方案
   这个数据模型设计方案对于特定的业务领域已经具备较高的灵活性,因此对象模型没有必要再过于复杂或高度抽象,代码的复杂性带来的问题很可能得不偿失。对象模型做必要的封装,使这个组织结构设计在使用时比较方便就足够了
   参考SAP系统。组织结构只是一种基础数据,他们的复杂性不在于数据本身的维护上,而在于其它业务模块对他们的使用。实现灵活的业务设计,基础数据本身的灵活性只是一个方面,如何让业务系统在使用这些基础数据时的逻辑处理规则也具备可配置性,是比较深层次的话题。同样,如果实现了这个目标,对象模型完全没有必要再做过多抽象,与数据模型一一对应也足够用了,这就是SAP、Oracle等这种大型系统中看不到太多面向对象痕迹的原因
   从这个观点来看,Martin尝试使用对象模型来描述这些复杂的业务概念模型就是一种错误的选择,也具有一定的误导作用
4. 这个数据模型只是一个简单的示例,实际中可以灵活的变化。
   例如在大型生产企业中,所有的组织(节点)对象用一个表来保存可能不大现实,例如公司、工厂、车间通常是生产组织结构的主要类型,他们可能都具备一些基本属性,但都有各自特殊的属性,很自然就会出现下面这种设计方式
   
   都具备的属性保存在"组织结构基本数据表"中,各自特殊的属性分别保存在公司、工厂等其它表中,使用一对一的关联关系
   同样规则也不局限于示例中的这种形式,不同的规则也可以象上面这样分不同的表保存
   同样,不管表结构如何设计,对象结构并不一定是继承等关系,组合、聚合、关联等都可以
   如果业务模块对这些基础数据的使用也具备较高的可配置性,一般都会存在很多这样的设计方式

抽象的责任模型
既然作为一种模式当然不能局限于组织结构,所以抽象概念就有了参与者Party、责任关系Accountability、委托方Commissioner、责任方Responsible,例如参与者Party的对象模型可能类似于:
   
上面pattern 3组织结构示例中的Parent_Org_Id、Child_Org_Id就分别对应到Commissioner、Responsible等
在具体业务设计中完全没有必要使用过于广泛的接口,在特定的问题域内进行适当抽象即可
上图中Organization、Person与Party之间是一种泛化关系,但不一定是接口的继承,形式上可能类似于pattern 3中的Organization3Type,即通过可配置的类型进行泛化,这就是书中提到的Party Type Generalizations

Operating Scope操作范围、Time Period有效时间
例如在BOM结构中有效时间段是必需的,对于operating scope,书中提到的例子那种情况下也是有必要的

posted on 2008-04-08 21:52 RicCC 阅读(2389) 评论(17)  编辑 收藏 所属分类: Architecture & Design

Feedback

#1楼  2008-04-08 23:35 Justin      

-----------Rose (UML) ------------|---------PD---------
业务建模->领域模型(关键抽象) ->|->CDM ->PDM

还是应该先有CDM然后才有PDM,使用PD,是可以直接从CDM生产PDM的,而CDM则应该由领域模型推出来,而领域模型则是由业务建模后进行对象职责划分经过需求、设计、开发等集体讨论出来的。   回复  引用  查看    

#2楼  2008-04-09 01:18 怪怪      

好文.

LS的说的太理论化。 说实话我一直不能完全认同这种观点。 另外,具体到数据与对象, 个人认为箭头到底是 -> 还是 <- ,也不必太死, 并不是一概而论就会一帆风顺的。 我们要的是真正能够解决问题的软件, 从来没有证据证明, 什么样的方法和过程能够更快的产生更好的软件。

反过来看, 只要软件满足需要(包括应对变化、重用等需求), 相反它到底是如何构建的根本无所谓。 还是我过去说的, 我们应该对业务如何由计算机系统来表达和运转进行抽象, 而不是拘泥于条条框框, 单纯的去玩概念。 很显然, 如果不是构建软件, 甚至仅仅不是基于面向对象的概念,很多现在流行的方法看上去就会变得毫无根据和依托; 这说明这些东西根本不是本质性的。

就像LZ说的,有时候引入不必要的东西,反而是错误选择, 比如把问题给人为的复杂化, 做了很多根本和“业务如何由计算机系统来表达和运转”这一根本目标毫无关系的工作。   回复  引用  查看    

#3楼  2008-04-09 01:24 怪怪      

关于最后一个例子, 其实从根本上来讲是一个可扩展的设计, 只是当相关的业务概念(比如组织结构)变的越来越庞大, 一些场景下的性能问题值得考虑。

感觉这个设计即使刨除业务之后与数据库设计的根本道理也是暗合的, 所以更可能是一种正确的方向。 对的东西往往是相通的, 而不对的东西则各有各的特色, 所以容易引入矛盾。   回复  引用  查看    

#4楼  2008-04-09 08:35 李战      

路过,看热闹。   回复  引用  查看    

#5楼  2008-04-09 08:49 Justin      

@怪怪
几年以前的项目就一直这么做了,没觉得那里理论化,这样从前到后是没有断层的。CDM->PDM是非常简单的,使用PD这个过程是全自动的。而之前的步骤更谈不上理论化吧?

当然,如果结果是能做出客户满意的东西,过程确实不重要。但是考虑未来的维护、升级、换代、人员流动、完整的需求和设计文档和模型是最重要的资料,谁能否认好的过程更容易产生好的结果呢?

不过至于过程的优劣等就没必要讨论了,萝卜白菜各有所爱吧。
  回复  引用  查看    

#6楼  2008-04-09 09:21 怪怪      

我不是说你的实践理论化, 你的实践很顺利, 说明你针对的问题还是比较适合这个解决办法。

我是说"还是应该"怎么怎么样等说法理论化。 好的过程也是千差万别, 同时好的过程不代表就能导致好的结果: 美国的民主过程得到了好的结果, 而伊拉克则没有~

当然这些属于诡辩的范畴了; 唯一我想说明的是,你的实践, 即使在你的问题上,也不见得就代表最好的实践了。进步是要依靠反思的, 在这方面, 我站在的LZ这一边而已 :)   回复  引用  查看    

#7楼 [楼主] 2008-04-09 09:36 RicCC      

@Justin
概念模型、设计模型(对象模型)、物理模型(数据模型)之间的对应关系比较直接时,Rose、PD、ERStudio等工具都能进行一定的自动转换,但映射关系比较复杂时一般都需要较大的修正或重新建模

另外你指出的那些概念是不同场景下的东西,例如在领域驱动设计里领域模型既是CDM,一定程度上也是设计模型

怪怪说的对,实际项目中灵活运用而已
例如领域驱动设计非常关注领域模型,它就比较反对概念模型和设计模型独立开的做法,其中的关键是对业务需求的理解、认识这一知识的传递问题,试想如果这些模型之间的转换关系很复杂,是由不同的角色来完成,那就意味着相同的知识采用了不同的描述方式,之间的转换关系复杂难以理解,也就无法避免知识在这个链路上传递转换时的丢失、误解   回复  引用  查看    

#8楼 [楼主] 2008-04-09 09:41 RicCC      

当然CMM成熟度比较高的企业对过程的控制很成熟,因此按照RUP流程一步步执行也不会有这些问题存在   回复  引用  查看    

#9楼 [楼主] 2008-04-09 09:59 RicCC      

@怪怪
关于性能方面,针对组织结构不会有什么问题,因为做这些东西一般是企业内部系统,考虑人和组织结构对应关系,再多也是几万、十几万人的规模,并且不同的业务领域、地区子集团都会使用不同的系统来解决,比较少需要集中维护

假如将这个设计运用在类似亚马逊的商品目录、商品与商品目录对应关系上,就需要针对性能做特别的考虑了   回复  引用  查看    

#10楼  2008-04-09 10:17 Anders Cui      

好文!   回复  引用  查看    

#11楼  2008-04-09 10:34 bmrxntfj      

领域模型的实现不止一种,实话说我个人不喜欢什么PDM
老怪说得好:业务如何由计算机系统来表达和运转
最初的时候,老外用二进制表达现实。只不过现在是oo了。
比如说一个订单,现实中应该有一个总价(totalAmount),但在程序设计的时候,可能我们只有一个单价和数量。需要总价的时候,临时去计算。也就是说,程序并没有表达出现实。   回复  引用  查看    

#12楼  2008-04-09 13:23 怪怪      

@RicCC
"相同的知识采用了不同的描述方式"

这个是非常切中要害的一点, 不过可能我比较擅长中小规模的组织吧, 我最敏感的倒不是知识传递的问题, 而是隐藏的知识重复带来的祸患。其实即使是你说的“对应关系比较直接”的情况, 也照样存在知识的重复, 只是用了一些框架和工具帮助我们后, 这种问题就不明显了。

另外,Bob大叔那本《敏捷》里,我印象最深刻的就是他改了10多年的那个烧咖啡机的例子。 有时候出现这种“对应关系比较直接”的情况, 很多实体不过是糖豆罢了;实际上一点不能体现抽象和面向对象的真正作用, 按照他的说法, 全都是“具体类”、“水蒸气类”。

可当一个问题深入理解, 如果产生出来的模型和对象比较“诡异”(但反而更接近事情的本质)的时候, 往往可能和实际事物以及PDM自身特点或要求相异,这时候很多工具和框架就不那么好使了。

关于性能方面, 确实如你所说, 干了两年Web(虽然还没开花结果), 思维有点变化了。 其实我自己做这个的时候, 是不会优先考虑性能的, 优化是最后的事情了; 不过越是没有干也没有碰到的事情, 我越是习惯于提心吊胆的提醒自己, 就好比上次和你争论的关于文档结构和语义的问题 :P。

所谓杞人就是我这样的人吧 呵呵

@bmrxntfj
这个有时候是一个成本问题。 我们完全可以记录总价, 然后搞个事件, 单价或者数量一遍, 总价就重新计算并且再次记录。

但是也不能单纯的认为是一个成本问题。 我觉得很难说, 这样实现了就等于表达现实。为什么这么说呢?因为比如现实很可能是, 总价只计算一次, 至于你是前天晚上算好, 还是当着客户面摁计算器, 并没有啥本质上的区别。 这样计算总价这件事, 并无任何不妥。

如何选择设计和实现, 往往是看咱们一开始是如何做出假设的, 这也是Linus能够有足够理由攻击面向对象的一个内涵: 非常不幸的, 大多数人做出的假设, 大部分可能是错的....   回复  引用  查看    

#13楼 [楼主] 2008-04-09 18:31 RicCC      

@怪怪
模式本身就是用来消除重复提高重用,感觉呢,过于抽象和集中的职责会带来不少问题,针对不恰当的运用模式而给项目带来不必要的复杂性的反对声音也很多;重复的东西太多成本和控制难度都比较高

对于重复性方面,几年的项目下来已经体会的比较深刻了,我想.Net的世界这种情况也应当是比较普遍的;而对于另外这种情况,找一些较大的项目比较彻底的采用面向对象的思想应该能够获得有事实支撑的经验,但不是轻易能这样冒险的

所以呢现实状况总是这样的: 扫除一定障碍(让主力军不用与他们纠缠),克服一定困难(什么困难都没有就不用程序员了),留有一定缺陷(总有后续待改善的),基本算是到达目的地(难得有项目达到完美程度)
本着中庸思想,对大部分概念、方法不排斥,不崇拜,但力求掌握他们怎么用,能够灵活运用。能够达到这种境界,很多时候也比较容易抓住事物的本质

好像把话题扯远了
上次的讨论后来给忘了,刚翻出来看了下,你后来的回复是抓到我们分歧的主要地方了   回复  引用  查看    

#14楼  2008-04-09 19:14 一水 [未注册用户]

很好,我想转载一下!   回复  引用    

#15楼 [楼主] 2008-04-09 20:29 RicCC      

@一水
没问题   回复  引用  查看    

#16楼  2008-07-04 21:36 miami [未注册用户]

谢谢
http://miamiguide.cn/Real_Estate   回复  引用   

posted @ 2008-09-18 18:07  YFeng_Lee  阅读(713)  评论(0编辑  收藏  举报