软件方法(下)第8章Part14:不要因为偷懒或炫耀而定义组合

DDD领域驱动设计批评文集>>

《软件方法》强化自测题集>>

《软件方法》各章合集>>

8.3.3 识别关联关系

8.3.3.1 关联的进一步细分

是否进一步细分各种关联,各种面向对象方法学观点不同。有的认为关联就是关联,不用再细分,有的则认为需要进一步细分。

例如,James J. Odell就把聚合分为6种并详细讨论,如图8-117。

图8-117 摘自Journal Of Object-Oriented Programming Vol 5, No 8. , James J. Odell , 1994

UML规范采取的是中间路线,把关联分为三种:普通关联、聚合(Aggregation)和组合(Composition)。

用图形表示,普通关联是一根直线,聚合有一端是空心菱形,组合有一端是实心菱形,如图8-118。

图8-118 三种关联的图示

在UML元模型中,把它们视为属于三个不同的AggregationKind,如图8-119。

图8-119

从元模型上看,“聚合”应该叫作“分享型聚合”,“组合”应该叫作“组合型聚合”,但本书还是使用“聚合”、“组合”,原因阅读后文自知。

聚合和组合都表示“整体-部分”的关系,在类图中,菱形一端表示整体,另一端表示部分。

相对于聚合,组合还有两条额外的约束:

(1)在同一时刻,部分对象只属于一个整体对象;

(2)整体对象被销毁,部分对象也要销毁;

虽然UML定义了聚合的概念,但实践中要不要使用聚合,经常会引起争论。在聚合关联中,部分对象同一时刻可以被多个整体对象共享,使得“整体-部分”的概念变得模糊,和普通关联难以区分。

James Rumbaugh等人在《UML参考手册(第2版)》中认为聚合是建模的“安慰剂”。

图8-120 摘自Unified Modeling Language Reference Manual, 2nd Edition, James Rumbaugh, Ivar Jacobson, Grady Booch, 2004

Craig Larman认为不需要使用聚合,在合适的情况下使用组合即可。

图8-121 摘自Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development, Third Edition, Craig Larman, 2004

本书的做法和Larman一致,不使用聚合,有必要表达“整体-部分”关联时,仅使用组合

含义模糊的聚合如图8-122。“微信群有微信账户”,而且微信群解散,微信账户还在,所以把“微信群”和“微信账户”之间的关联设为聚合,多重性为多对多。

图8-122 含糊的聚合举例

图8-122可以改为更清晰的图8-123。

图8-123 使用组合

图8-123将“微信群员”和“微信账户”分离,“微信群员”仅属于一个“微信群”。如果“微信群”对象消失,“微信群员”对象及相关属性值也就消失了,但“微信账户”还在。

注意,即使是图8-123,也要有足够证据才能建模成组合。如果只是玩文字游戏,图8-123也可以变成图8-124,从另一个角度来“组合”似乎也未尝不可。

图8-124 另一个角度的组合

以上说的“足够证据”,指的是是否有利于责任分配。

8.3.3.2 组合的作用

把关联定义为组合关联,意味着部分对象成为整体对象的部件,外部的对象不能发消息给部分对象,只能发给整体对象,再由整体对象分解和分配给组成它的部分对象,如图8-125所示。

图8-125 组合关联影响责任分配

类图上有很多类,类之间的密切程度会有所不同。如果根据目前责任分配的情况,判断某些类之间协作的频率远超过它们和外部其他类协作的频率,而且预判将来也可能是这样,那么通过建立组合关联来强制把它们封装成一个整体来分配责任,是合算的。

和划分部门类比

建立组合关联和公司的部门划分有类似之处。

公司不划分部门,老总一个个员工派任务也能达到目标,只是效率不高,而且不管出现什么变化都要打开老总的“代码”来修改。

划分部门之后,老总就省心多了,只需要给各部门分配大任务,部门把任务分解,再分配给部门内的各小组,各小组再把任务分解,分配给小组内的小小组……。这样,各种逻辑就会分散到各个部门、小组、小小组。

当然,这是有代价的。划分部门之后,上级就不要越过下级去找更下级,下级也不能想找谁就找谁,都要讲基本法。

如果部门内各下级之间的协作频率远高于和其他部门协作的频率,说明这样的代价是值得付出的,部门划分以及责任的分解和分配是合理的。反之则说明不合理。

不要因为偷懒或炫耀而定义组合

可以想象,如果公司老总在没有充分调研员工能力以及公司业务的情况下,着急过一把官瘾,胡乱划分部门,提拔干部,会大大损害所有人的利益,很容易激起反抗。

然而,如果软件开发人员着急过“架构师”的瘾,胡乱定义组合(聚合)关联,并不会激起各个代码片段的反抗。计算机程序目前还没有产生自我意识,没有Neo(电影“The Matrix”,《黑客帝国》),特别乖,爱怎么整都可以。

以前可能是为了偷懒而胡乱定义组合(聚合)关联。

如图8-126,如果建模为普通关联,还得给关联想个合适的名字。算了,懒得想,貌似说“订单有顾客”也说得通嘛,“有”那不就是组合(聚合)吗?干脆加个菱形吧,这样还省事,而且相对于一根直线,菱形让人有高大上的感觉!

图8-126 为了偷懒滥用组合(聚合)

最近一些年,由于DDD话语对“聚合”过度吹嘘,某些软件开发人员把“划分聚合”看成“有架构师能力”的表现,于是在没有足够证据的情况下,兴奋地把“聚合”到处用——哈哈,我会切割系统了,我架构师了!

这些人的思维经常是颠倒的:先拍脑袋定“聚合”,然后就按DDD话语的建议来使用,包括外部对象的访问、创建、访问数据等,然后再用实现的代码(show me the code嘛)来“证明”之前划分的“聚合”是正确的,形成一个“完美”的循环。

用公司类比,相当于公司老总拍脑袋把张三、李四、王五等人划分成一个部门,并任命张三为部门领导,然后通过张三发号施令,再用这个“事实”来“证明”张三作为部门领导是正确的。当然,这样类比不完全贴切,后文还会提到。

定义组合(聚合)务必谨慎。在有足够的核心域逻辑作为证据之前,应该先建模为普通关联。经过序列图、状态机图等进一步建模核心域逻辑之后,如果有进一步证据支持定义组合(聚合)关联有利,可以定义组合(聚合)关联用于指导后续其他用例的责任分配。如果没有足够证据,不定义组合(聚合)关联也无所谓。

图8-127 学员发给我评点的一张带有大量菱形的类图(类的信息已隐去)

8.3.3.3 和《设计模式》用语的区别

说到这里,我们要整理一下类之间的关系,用类图表示如图8-128。

图8-128 “类之间的关系”各概念之间的关系

从图8-128可以看到,泛化、关联和依赖在一个抽象级别,普通关联、聚合和组合在一个抽象级别。此处我们把“聚合”定义为“组合之外的其它聚合”,同样,“普通关联”定义为“聚合和组合之外其他关联”。

否则,各种关联概念之间的关系应该像图8-129:

图8-129 各种关联概念之间的关系:另一个版本

按照图8-128,我们在表达的时候要注意,说“泛化和关联”可以,但说“泛化和聚合”、“泛化和组合”或“继承和组合”是不合适的。

而GoF所写的”Design Patterns: Elements of Reusable Object-Oriented Software”(《设计模式》),第1章中有一句被广为流传的话:

Favor object composition over class inheritance.

优先使用对象组合而不是类继承。

这句话常让人误解组合和继承是一个级别的,其实,根据GoF《设计模式》的用词,这句话中的“组合”应该近似于UML中的“关联”。

如图8-130,在GoF《设计模式》中,给出这句话之后,作者接下来讨论了aggregation(聚合)和acquaintance(认识)的区别,并且说acquaintance有时也被称为association(关联)或using(使用)。然而,在后面的内容中,作者把这几个词全部抛弃,一律使用composition。

图8-130 摘自Design Patterns: Elements of Reusable Object-Oriented Software, Erich Gamma , et al. , 1995

根据GoF书中内容猜测,其中用词和UML以及本书的用词的对应关系可能如图8-131。左右对应为:①继承=泛化;②组合≈关联;③认识≈普通关联;④聚合≈聚合+组合。

图8-131 《设计模式》话语和UML话语中的对应

以上仅属推测,而且书中的叙述也是有矛盾的,例如这一句:

Consider the distinction between object aggregation and acquaintance and how differently they manifest themselves at compile- and run-times.

考虑对象聚合和认识之间的区别,以及它们在编译时和运行时如何不同地展现自己。

这句话好像是在说“聚合”和“认识”在编译时和运行时有所不同,这和图8-131中的对应③和④矛盾。

另外,图8-130的片段中,把association(关联)和using(使用)说成同一个意思,这个也是让人困惑的。using听起来更像是UML话语中的“依赖”。

8.3.3.4 DDD****话语中的“聚合”和“聚合根”是伪创新

(待续……)

Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition) by Craig Larman Publisher: Prentice Hall PTR; 3 edition (October 30, 2004)Applying UML and Patterns is the world\'s #1 business and college introduction to \"thinking in objects\"and using that insight in real-world object-oriented analysis and design. Building on two widely acclaimed previous editions, Craig Larman has updated this book to fully reflect the new UML 2 standard, to help you master the art of object design, and to promote high-impact, iterative, and skillful agile modeling practices.Developers and students will learn object-oriented analysis and design (OOA/D) through three iterations of two cohesive, start-to-finish case studies. These case studies incrementally introduce key skills, essential OO principles and patterns, UML notation, and best practices. You won\'t just learn UML diagramsyou\'ll learn how to apply UML in the context of OO software development.Drawing on his unsurpassed experience as a mentor and consultant, Larman helps you understand evolutionary requirements and use cases, domain object modeling, responsibility-driven design, essential OO design, layered architectures, \"Gang of Four\" design patterns, GRASP, iterative methods, an agile approach to the Unified Process (UP), and much more. This edition\'s extensive improvements includeA stronger focus on helping you master OOA/D through case studies that demonstrate key OO principles and patterns, while also applying the UMLNew coverage of UML 2, Agile Modeling, Test-Driven Development, and refactoringMany new tips on combining iterative and evolutionary development with OOA/DUpdates for easier study, including new learning aids and graphicsNew college educator teaching resourcesGuidance on applying the UP in a light, agile spirit, complementary with other iterative methods such as XP and ScrumTechniques for applying the UML to documenting architecturesA new chapter on evolutionary requirements, and much moreApplying UML and Patterns, Third Edition, is a lucid and practical introduction to thinking and designing with objectsand creating systems that are well crafted, robust, and maintainable.http://img470.imageshack.us/img470/1586/013148906201sclzzzzzzz0nt.jpghttp://www.ebookee.com.cn/Applying-UML-and-Patterns-An-Introduction-to-Object-Oriented-Analysis-and-Design-and-Iterative-Development-3rd-Edition-_34091.htmlhttp://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=sr_1_1?ie=UTF8&s=books&qid=1219551411&sr=1-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值