首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

5.6  Poltergeist(恶作剧鬼)

反模式名称:Poltergeist

别名:Gypsy(吉普赛人)[Akroyd 1996]、Proliferation of Classes(类增殖)[Riel 1996]和Big DoIt Controller Class[Fowler 1997]

最常见规模:应用层

重构方案名称:Ghostbusting(捉鬼)

重构方案类型:过程

根源:懒惰、无知

不平衡的力量:功能管理、复杂性管理

轶事证据:“我不确定这个类到底做什么,但它肯定很重要!”

5.6.1  背景

当Michael Akroyd在1996年的Object World West会议上提出Gypsy反模式时,它把Gypsy类短暂出现然后断续消失的性质比做今天来了明天又走了的“吉普赛大篷车”。在研究Akroyd的模型时,我们希望在该反模式的总体名称中传递有关该Gypsy类的调用函数的更多信息。这样,由于我们觉得既然poltergeist表示“bump-in-the-night(夜里神出鬼没)”的“不停歇的鬼”,这个术语更好地代表了该反模式“突然跳出来造成某些事”的概念,同时又保持了最初的Gypsy名称的“刚才还在这里,突然就消失了”的风味(见图5-14)。

在LISP以及很多其他语言中,总有一些既纯洁又邪恶的程序员,他们非常乐于在系统中利用特定语言函数的“副作用”来完成一些关键功能。分析和理解这样的系统实际上是不可能的,任何对复用的尝试都会被看作是疯狂的举动。

与Poltergeist“控制器”类相似,在实现中使用“副作用”来完成任何重要任务都是对语言或架构工具的不正确使用,都应避免。

5.6.2  一般形式

Poltergeist类在系统中只承担有限的责任和角色,因此,它们的有效生命周期相当短暂。Poltergeist会建立不必要的抽象,让软件设计变得混乱。它们过度复杂、难以理解而且难以维护。

该反模式通常出现在熟悉过程建模但新接触面向对象设计的设计人员定义架构的时候。在该反模式中,可以发现一个或多个像鬼魂一样虚幻的类,它们只是短暂地出现,用于启动其他更为持久的类中的某些操作。Akroyd称这些类为“Gypsy Wagon(吉普赛大篷车)”[Akroyd 1996]。一般而言,Gypsy Wagon作为控制器类出现,只是按照预定的顺序调用其他类的方法。它们通常很明显,因为它们的名称常常带有_manager或_controller后缀。

Poltergeist反模式常常是某些缺乏经验、没有真正理解面向对象概念的架构师故意设立的。Poltergeist类建立的是不良设计制品的关键原因有3个:

(1)它们不是必需的,所以它们每次“出现”的时候都会浪费资源。

(2)它们是低效的,因为它们要使用一些冗余的导航路径。

(3)它们让对象模型产生不必要的混乱,阻碍了正确的面向对象设计。

5.6.3  症状和后果

  ● 冗余的导航路径。

  ● 瞬时联系。

  ● 无状态的类。

  ● 临时的、短持续时间的对象和类。

  ● 只是为了通过临时联系“播种”或“调用”其他类而出现的单操作类。

  ● 具有“类似于控制”的操作名称,例如start_process_alpha的类。

5.6.4  典型原因

  ● 缺乏面向对象架构。“设计师不懂面向对象”。

  ● 使用不正确的工具来完成工作。与普遍观点相反,面向对象方法并不一定是解决所有问题的正确方法。就像一张海报曾经说的:“没有正确的方法来做错事。”意思就是,如果面向对象不是正确的工具,就没有正确的方法来实现它。

  ● 说明灾难。和The Blob反模式一样,管理层有时会在需求分析时做出架构承诺。这是不合适的做法,常常会导致一些问题,这个反模式就是其中之一。

5.6.5  已知例外

Poltergeist反模式没有例外。

5.6.6  重构方案

Ghostbuster(捉鬼人)解决Poltergeist反模式的方法是从类层次关系中完全移除它们。但是在移除它们之后,由它们“提供”的功能必需被替换。这项工作很简单,只要简单地调整就可以纠正架构。

关键之处是把Poltergeist类最初封装的控制操作移动到它们调用的相关类中。下一部分对此进行了详细解释。

5.6.7  示例

为了更清楚地解释Poltergeist反模式,考虑图5-15中制造桃子罐头的例子。我们可以发现PEACH_CANNER_CONTROLLER类是一个Poltergeist类,因为:

  ● 它到系统中的所有其他类都有冗余的访问路径。

  ● 它所有的联系都是瞬时的。

  ● 它没有状态。

  ● 它是临时的、短持续时间的类,只是为了通过临时联系调用其他类而跳出来。

PEACH_CANNER_CONTROLLER

 

CALENDAR

 

Evaluate Rule Base

 

CANNER

 

CHOPPER

 

PEELER

 

WASHER

 

PEACHES

 

PROCESS_TIMER

 

图5-15  控制器类

在这个例子中,如果我们移除Poltergeist类,剩下的类就会失去交互的能力。处理过程不再有任何的顺序。因此,我们要把这种交互能力放置到剩下的层次关系中,如图5-16所示。请注意每步处理都增加了特定的操作,以便各个类可以相互交互并产生结果。

5.6.8  相关解决方案

The Blob反模式中讨论的“80%方案”会产生一些看起来很像Poltergeist的内容。该方法产生的“协调器”类仍然管理系统的所有或大部分功能,通常显现出很多Poltergeist类的特点。

5.6.9  对其他视角和规模的适用性

我们选择把这个反模式放在开发性反模式这一章而不是和架构性反模式放在一起,是因为虽然它的确可能是未能正确建立系统架构的结果,但更可能出现在开发人员边实现系统边进行系统设计(通常就是在座位边上设计)的情况下。这是否证明了Poltergeist实际上是失败的管理则取决于读者的判断。

与大多数开发性反模式一样,架构和管理视角在最初预防和持续监督防止它们的方面都扮演了重要的角色。往往通过架构视角才能发现正在出现的反模式,而在未能完全预防反模式时,只有通过有效的管理才能正确解决它。

管理者应该非常注意,保证尽早让具备适当资格的面向对象架构师来评估面向对象架构,然后持续防止新手产生类似于这个反模式的错误。一开始就为良好的架构投资!

小型反模式:Boat Anchor(船锚)

反模式问题

Boat Anchor是指在当前项目中没有起到有益作用的那些软件或硬件。而且Boat Anchor往往具有相当高的成本,这使得当初对它的采购显得更具有讽刺意味。

获取Boat Anchor的原因在当时往往是非常有说服力的。例如,政策或程序性的关系可能会要求购买和使用特定的硬件或软件。这是该软件项目的启动设想(或限制)。另一个强制性的原因是某个关键的管理者相信获取这些东西的作用。有一种名为“贵宾行销”的销售实践就是把销售目标定位在具有采购权的高级决策制定者。贵宾行销通常把重点放在小型或中型公司的行政总监身上。在进行适当的技术评估之前,他们可能就会做出采购该产品的承诺。

管理者和软件开发人员要面对的后果就是需要投入大量的精力来让采购的产品可以工作。在投入了大量时间和资源后,技术人员认识到这个产品在当前的上下文环境中没有用,于是放弃它而改用别的技术方法。最终,Boat Anchor被扔到某个角落里,渐渐蒙上一层灰尘(如果是硬件的话)。

重构方案

良好的工程实践包括提供后备技术,也就是某种替代方法,只需要最少的软件返工就可以把它替换进来。对后备技术的选择是一项重要的风险缓解策略。应该为大部分基础技术(大部分软件所依赖的),以及其他高风险领域中的技术确定相应的后备技术。应该在选择过程中对后备技术和关键途径技术一起进行评估。我们建议对关键途径和后备技术都使用评估许可(大部分供应商都可以提供)来建立原型。

相关反模式

在Irrational Management反模式中解释了理性决策制定过程。理性决策制定可以被用做客观的技术选择过程来在采购前发现Boat Anchor。对Smoke and Mirrors反模式的解决方案说明了采购前技术评估的实践方法,包括审查产品文档和购买前培训。

反 模 式

 
 

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论