IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Java technology  >

Java 技术:品味“Bitter Java”

反模式可以如何提高编程

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

Bruce A. Tate (bruce.tate@j2life.com), 独立顾问, J2Life,LLC

2002 年 3 月 21 日

设计模式对软件开发来说很重要,这一点从它在技术贸易新闻中所占的数量就可见一斑。不过,鉴于其在开发过程中的实用性,设计模式只解决了问题的一半。反模式 ― 描述“对产生绝对负面结果的问题的一种常用解决方案” ― 旨在通过向 Java 程序员展示如何避免常见的 Java 陷阱来解决问题的另一半。Bruce Tate 是一位反模式专家,也是撰写 Bitter Java一书的知名作者,他在本文中说明了反模式如何及为什么会成为设计模式必要的和补充的伴侣。他提供了反模式具体的示例 ― 往返旅程反模式魔法 Servlet 反模式― 然后描述了如何应用其中的知识来改进您的程序和开发过程。

在东田纳西州寒冷的一天,我的橡皮艇摇摆不定地停靠在一个十六英尺高的瀑布顶上,这个瀑布名叫州界瀑布(State Line Falls)。这条急流因为经常吞噬小船和人而臭名昭著。从顶上望过去,急流拐角处没有什么危险的迹象,但是我知道。几天以来,我在清醒的每一刻心中都记得旅行指南中对它的描述。五个卡车般大小的石块形成了四道狭缝。我只能在穿过急流的前几秒看到整个瀑布。对于这四道狭缝中的三个来说,您的岳母要穿过去可能会太费力、太危险,它们因此而闻名。急流劈波斩浪地冲过第四道“友好的”狭缝,加速前行,拍打在凹凸不平石块上。我的职业是程序员,还是两个孩子的父亲,也算一个中等技能的橡皮艇漂流爱好者。我连穿过旅游手册中作为“旁注”而描述的五级瀑布的本事都没有。我在这里到底要干什么?

作为程序员的我也多次问过自己相同的问题。在我准备解决一个不熟悉的问题时,如果进度压力越来越大,而且失败将带来可怕的后果,我也曾踏上一个类似的悬崖边缘,这种情况不胜枚举。在本文中,我将讨论一种能够帮助程序员走出此类困境的工具: 反模式。我还会指出反模式能够以何种方式补充您的设计模式学习。如果您经常访问 developerWorks,您就会看到上面介绍了很多设计模式,也会看到对其内在价值的争论。可是,虽然 Eric Allen 的关于错误模式的文章(请参阅 参考资料)对它们的有效性给了您一个暗示,但您对反模式可能还不会有相同的认识。不只是您会这么想。几年来,开发者已经发布了很多关于设计模式描述很深入的书和文章,但有关反模式的相同社区却少之又少。我撰写本文的目的在于向您说明,反模式是设计模式的一个必要的和补充的伴侣。

使用设计模式重复成功策略

我在观察周界瀑布上的漂流时,想起了我所了解的事情。从和别人的谈话中,我了解到所有成功的漂流都是从第三个狭缝的右侧过去的,而且我必须快速地冲过急流,以避免碰上瀑布下浅水上面的石块。这些经验增强了我的信心,我不再理会旋涡的危险,冲进了急流的主干道。

虽然我在这些模式的术语中并没有考虑到这一点,我还是在使用设计模式。我将自己的策略建立在那些在我之前成功地通过急流的漂流者的经验之上。设计模式给予我信心,使我能够通过一个原本超越我技能水平之上的急流。我经常将这些相同的原理应用到编程和体系结构中;您可以通过观察一个策略反复的成功结果来学着解决给定的问题。有了设计模式,结果是肯定的。您可以利用自己的经验、观摩导师,或是从书上学习专家是如何做的。

我们的编程技巧中很多最重要的先进之处就是来自于设计模式。模型-视图-控制器(Model-View-Controller)模式指导我们有效地分割代码,在用户接口和模型之间定义一个良好的边界。发布-订阅(Publish-Subscribe)设计模式指导我们如何在不广播事件的情况下管理它们。其它的设计模式对各种 Java 框架产生了深远影响:用于远程通信的代理 EJB 接口、集合类、Swing 框架和很多其它框架。

我非常喜欢构建可重复过程。从这一点来讲,设计模式可以提供很多好处。设计模式强迫您考虑将问题分割成分立的子问题,其中有一些可以利用可重复解决方案来解决。设计模式还强迫您考虑如何正式地表示和传达设计经验,从而使其它人可以利用您的成果。

但是设计模式还不是足够的。如果您将编程问题想象成一个必须穿过的地区,那么设计模式最多只是一张局部地图。毕竟,如果已经存在一个完美的解决方案可以满足您的需求,您可能就会直接去买,而不是自己构建了。此外,随着支持的软件不断发展,基础结构 ― 地图上已有的道路 ― 也在迅速地改变。局部地图可以指引您避开某些危险,但不是所有危险。您将必须在地图之外的地区冒险,才能到达目的地。那么,如果迷失了方向,您会怎么做呢?





回页首


使用反模式避免落入痛苦的陷阱

我在急流中调整方向时,水流将我推向左边。橡皮艇漂流者必须洞悉高难度急流中的危险之处,我在这点上完成了要求。我知道在我之前有一些漂流者漂到左边并翻了船,而且我已经考虑过,并在脑海中练习了解决此问题的方法。经过此番准备,我奋力地划浆,将橡皮艇恢复到原来的方向。现在我有了一步一步战胜困难的机会。

下面是在反模式中考虑这个问题的方式:我从一个很难的问题开始。根据其它成功的解决方案,我选择一个计划:我的设计模式。我的计划出了问题,但我有所准备,通过在我的急流中分析其它失败的漂流作出响应:我在使用反模式。因为我有所准备,所以看出了问题,并调整我的方法以回到正途:我在重构。在高难度的橡皮艇漂流和编程中,从自己的错误中学习都是很有价值的,但也很痛苦。我更宁愿从别人的错误中学习。使用这种方法,我就能够试着解决通常远远超越我能力范围的问题了。

Antipatterns: Refactoring Software, Architectures, and Projects in Crisis(请参考 参考资料)一书的作者这样定义了反模式:

反模式是描述对产生绝对负面结果的问题的一种常用解决方案的字面形式。

这里的关键词是:

  • 字面形式:反模式是问题的描述,而不是代码的描述。这非常重要,因为我们可以迅速和有效地传递消息,而客户可以迅速地理解。
  • 常用:如果它不是模式,那它就不是反模式。您必须建立几个不同的运行较差的行为实例,最好是在不同的环境中,这样才能使错误上升到反模式的级别。
  • 负面结果:设计必须有可以观察的、负面的效应。

最著名的反模式 Y2K 向我们展示了这个激动人心的新领域的危机和出路。回想起以前,成千上万的开发者将日期编码成两位数字而不是四位数字,错误地比较这些数字就会导致数以万计的错误。很多杰出的研究者都预言这个问题将会泛滥成灾,但是经过人们对问题的深入研究,新的标识和重构技术已经很有效地修正了代码,以至于很少有人会碰到预言中那么多的问题。反模式类似于设计模式,是重复使用的解决方案。区别在于反模式有负面结果。当您为反模式做文档时,您将希望获取至少下面这些元素:

  • 名称:有时候反模式可能已经有一个或多个非正式的名称,这是由开发社区给出的。其它情况下,您就会希望自己选择一个名称。这个名称应该具有描述性,而且要简单。
  • 问题:问题描述了反模式有缺陷的解决方案,以及驱使开发者走向有缺陷的解决方案的推动因素。这个描述指导其他人如何找到问题。
  • 重构的解决方案:反模式有用的范围是:可以帮助我们从陷阱中解脱出来,或者完全避免这些陷阱。重构的解决方案是指导其它人如何修正问题的指南。




回页首


其它成功使用反模式的行业

很多其它行业 ― 最值得注意的是制造业 ― 使用某种形式的反模式,通常都是与设计模式相结合使用。当前的制造业者不遗余力地效仿其它同行成功的过程改进。例如即时(Just-in-Time)“设计模式”。即时制造是一种过程,它允许用减少库存和快速修正来解决质量问题,从而提高质量。过程中每个连续的步骤都使用由前一步即时递交的装配件。所有主要的汽车制造业者现在都使用这种技术。制造业者还采用了其它设计模式进行装配组织、测试以及数据收集。最好的制造业者并没有在这里停滞不前。他们还认识到对发现系统过程故障的需求。类似于 Zero Defects 和 Quality Circles 这样的程序让车间中的蓝领工人周期性地花一点时间讨论系统过程问题,以及如何尽可能地防止问题出现。一般的程序都能够为雇主节省大量维护所需的时间。行业中反模式的其它示例还包括:

  • 保健行业,研究者在这里查找和发布不良的饮食习惯,然后好的医生会使用这些信息来指导病人如何改变引起疾病的根源,而不仅仅是症状。
  • 法律执行,警官在这里与社区合作,确定和预防治安不良地区中的犯罪根源。这些程序可以显著地减少毒品服用和暴力犯罪的情况。
  • 出版行业,经过十多年对作者的忽略之后,最成功的出版商再次与作者以紧密地伙伴关系相互合作。这种伙伴关系有助于作者确定和改正不良写作习惯,从而写出更好的书。最成功的技术读物出版商就使用这种方法,而其它出版商正在效仿。




回页首


Java 语言中反模式的示例

如果反模式在其它行业中都很成功的话,那么程序员能不能也从中受益呢?我相信程序员能得到的还不止这么多。作为程序员,您如果想成功,只需要快速地识别出常见的陷阱就可以了。软件开发所使用的是一套难以置信的相反的工具、语言、方法和策略。让我们回头想想地图的类推。不同情况下的问题稍有不同。您需要具有归纳知识并将其转用到其它情况的能力,这样才能成功。设计模式倾向于定位在特定问题域上,而反模式就可以更具普遍性。实际上,您可能犯的很多错误以前就已经存在了。反模式有助于帮您在开发周期的早期识别出更多此类错误。如果您和多数程序员一样,那么花一点时间去理解当前环境中的陷阱可以为您节省大量时间和工作。Java 语言的发展向我们展示了很多有关错误的示例,这些错误是我们从其它编程的发展中借鉴的。

  • 早期的 EJB 实体 bean 实现慢如蜗牛,一部分原因是通信开销过于高昂。 经过一段时间之后,人们开始认识到其中一个显著问题是往返旅程。我们最终学会了使用类似于虚包的修正方法来重构这些解决方案。(请参考旁注 往返旅程反模式以了解细节。)其它开发者在 EJB 组件问世很久之前就碰到了这个问题。早期个人电脑上的数据库一直为性能问题所困扰,直到管理员学会了使用存储过程将多个数据库通信巩固为一体。早期的分布式系统开发者也发现了相同的问题,然后发布了虚包解决方案。
  • 常见的 Java 反模式的另一个示例是魔法 Servlet。这个非常基础的反模式(在旁注 魔法 Servlet 反模式中有详细描述)困扰了很多相对高级的客户。在这个反模式中,一个单独的 servlet 将处理视图、模型以及控制器逻辑。这样的设计使得维护几乎不可能实现,因为无论视图何时改变,您都必须改变模型逻辑,反之亦然。魔法 Servlet 也有比 Java 语言更早的渊源。此问题最常见的示例其实发生在 Visual Basic 中,程序员在 Visual Basic 中经常会向一个单独的控件(如按钮)附加 10K 大小的脚本。

这些问题只是涉及到表面。在每个新的领域中,Java 开发者都会重新发现一些旧的错误,而这些错误具有某种规律性。如果我们抱着扫清障碍的目的研究这些陷阱,就一定会免受一些痛苦。





回页首


使用反模式过程

希望我已经使您相信反模式是值得注意的。那么要将反模式与您每天的例行工作相结合,您又可以做些什么呢?图 1 展示了一个过程的大体步骤,它可以帮助您识别和解决反模式。我在 Bitter Java一书中(请参考 参考资料)更详细地讨论了这些问题。


图 1. 一个基本的反模式过程中的步骤
反模式过程
  1. 识别问题。在 Java 编程中,问题可能是错误、性能问题、难于维护的类,或是不断增大的内存占用量。
  2. 建立模式。如果您是一名软件工程专业的学生,那么您就会知道,随着您不断深入开发周期,修正一个错误的开销将呈指数上升。当您建立问题的模式时,您就给了自己在开发周期的更早阶段识别和修正更多问题的机会,您的获得也将数以倍计。使这个价值链向上移动的关键就在于建立模式,然后尽可能广泛地根据反模式操作。
  3. 重构代码。在这一步中,您将重构导致问题的代码。这一步是一个简单的错误修正,它适用于您迄今为止识别出的所有问题实例。您应该花时间去做一个完整的修正,而不是仅仅打一个补丁了事,如果错误可能会出现在同一位置,您还应该添加文档。您还会希望对各个步骤作出文档,从而将解决方案分发给其它人。
  4. 宣传解决方案。您在这里确保碰到问题的其它人懂得如何修正问题,并确保可能碰到陷阱的其它人知道要避开它。发布反模式可以更广泛地传播反模式的好处。
  5. 修正过程。您在这里构建一个隔开反模式保护性的屏障。修正可以采用很多不同的方式。改进测试案例可以快速地识别衰退。修正每日过程或通信渠道可以在问题发生之前预防它们。补充编码标准几乎能够消除某些类型的编码错误,如关于放置花括号或注释的错误。

这些步骤采用的方法是从特定到一般。您找到错误,然后建立模式、修正错误,最后修正过程。将其中某些步骤与您的日常例行工作相结合可以使您成为更好的程序员。但是,请不要在这里停下来。请利用您的反模式知识来修正过程,继续使价值链向上移动,并让您整个公司的程序员都变得更棒。您还可以发布反模式帮助您甚至不认识的程序员。如果您是一名程序员,并且是设计模式的爱好者,我保证您会发现反模式能够提供的不止这些。

我的漂流过程的剩下部分就有点虎头蛇尾了:我掠过瀑布表面、作自由落体运动,然后“扑”地一声轻轻落入激起的浪花中。这一天的剩下时间里,我划浆时一直在傻笑,没有办法停下来,也不想停下来,直到最后我安全抵达等在下面的汽车为止。



参考资料



关于作者

Author photo

Bruce Tate 是一位独立顾问和作家。他在 IBM 的各个领域工作了十二年,包括领导一个 Java 概念验证(proof-of-concept)小组。一个 Austin 新公司从 IBM 招募了 Bruce 来负责解决方案开发组织,不久以后 Bruce 离开了这个职位开始创建自己的企业: J2Life, LLC。他著有三本书,其中包括 Bitter Java ,一本关于 Java 反模式的书。请通过 bruce.tate@j2life.com与 Bruce 联系。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款