我们首次见到软件开发性反模式[①]是在Mike Akroyd的报告[Akroyd 1996]中,他是摩托罗拉公司和其他一些大型公司的软件实验咨询顾问。Akroyd反模式定义了面向对象软件设计中的经典问题。本章中的部分开发性反模式是对他的概念的延伸。所有Akroyd反模式都有一个吸引人的特点,就是它们都包含了一个重构方案。通过结合这个重构方案,让反模式具备了颇有价值的用途:它不仅指出问题,还告诉你应该如何加以解决。
正确的反模式定义了从负面解决方案到正面解决方案的迁移(或重构)。只描述了负面解决方案的反模式被称为伪反模式。可以把伪反模式看做是通过电子邮件进行的激烈抨击。在使用过Akroyd反模式之后,我们在因特网上发现了反模式和伪反模式的例子。PLoP会议也讨论了一些与反模式相关的论文,例如Big Ball of Mud [Foote 1997]。
5.1 软件重构
开发性反模式的关键目标是描述有用的软件重构形式。软件重构是一种代码修改形式,用于改善软件结构以支持后续的扩充和长期维护。在大多数情况下,其目标是在不影响正确性的条件下转换代码。
良好的软件结构对系统的扩充和维护是必要的。软件开发是一项无序的活动,因此系统的实现结构往往会偏离通过架构、分析和设计而规划出的结构。软件重构是改善软件结构的有效方法。生成的结构并不一定要与最初规划的结构一样。结构发生变化的原因在于,程序员在重构过程中了解到一些改变了编码实现方案上下文背景的限制和方法。正确地使用重构是编程过程中的一项相当自然的活动。例如,本章后面讨论的Spaghetti Code反模式的解决方案定义的软件开发过程就结合了重构。
我们强烈建议先重构,再进行优化。优化常常要求在软件结构上做出折中。理想情况下,优化只影响程序中的一小部分。先进行重构有助于把优化代码与软件主体分割开。
正规重构变换
正规重构变换包括超类抽象、条件消除和聚合抽象。这些正规重构起源于Opdyke的博士论文[Opdyke 1992]。它们被称为正规重构的原因在于可以证明它们的实现不会影响程序的正确性。把这些变换自动化也是可行的。下面的重构涉及对对象类、实现和关系的改变。
● 超类抽象。这种重构应用于两个或更多相似的类。超类抽象建立一个抽象类来合并数个具体类中的共同实现。要进行超类抽象,对程序的转换包括:(1)把相似的方法签名转换成通用方法签名;(2)建立一个抽象超类;(3)修改代码以合并选择的实现;(4)把通用方法迁移到抽象超类。
● 条件消除。在类的结构和行为严重依赖于某个条件语句时可以应用该重构。主要步骤是:(1)根据每个条件建立相应的新子类;(2)把操作代码从条件类迁移到新的子类;(3)调整对类的引用指向适当的子类。最后这步变化可能会影响到构造函数、类型声明以及要求调用重载的方法。修改过的引用应该维持条件类的原始逻辑状态,作为新类中的不变性断言。
● 聚合抽象。聚合抽象通过重新组织类的关系来改善它们的结构和可扩展性。这种变换可以采用多种形式:(1)把继承关系转换成聚合关系;(2)迁移聚合类到构件关系;或者(3)迁移构件关系到聚合关系。
这三种粗粒度的重构依赖于数十个几乎所有程序员都熟悉的细粒度程序变换[Opdyke 1992]。这些细粒度变换的例子包括:(1)重命名类、方法和属性;(2)建立新类;(3)在类之间迁移功能;(4)把直接引用转换成间接指针,等等。要获得完整的列表,参阅Opdyke的论文[Opdyke 1992]。





