1.9.6 第5阶段:进化
这是开发周期中,传统上称为“维护”的一个阶段,是一个含义广泛的术语,包含了从“让软件真正按最初提出的方式运行”到“添加用户忘记说明的性能”,到更传统的“排除暴露的错误”和“在出现新的需求时添加性能”。所以,对术语“维护”有许多误解,它已经有点虚假的成分,部分因为它假设我们已经实际上建立了原始的程序,且所有的需要就是改变其中一些部分,加加油,防止生锈。也许,有更好的术语来描述所进行的工作。
此处将使用术语“进化”(evolution)[1]。这就是说,“我们不可能第一次就使软件正确,所以应该为学习、返工和修改留有余地”。当我们对问题有了深入的学习和领会之后,可能需要做大量的修改。如果我们使软件不断进化,直到使软件正确,无论在短期内还是在长期内,将产生极为优雅的程序。进化是使程序从好到优秀,是使第一遍不理解的问题变清楚的过程。它也是我们的类能从只为一个项目使用进化为可重用资源的过程。
“使软件正确”的意思不只是使程序按照要求和用例工作,还意味着我们理解代码的内部结构,并且认识到它能很好地协同工作,没有拙笨的语法和过大的对象,也没有难看的暴露的代码。另外,必须认识到,程序结构将经历各种修改而保全下来,这些修改贯穿整个生命期,也要认识到,这些修改可以是很容易进行和很简洁的。这可不是小成就。我们不仅必须懂得我们正在建造的程序,而且必须懂得这个程序将进化我称之为改变矢量(vector of change)[[2]]。幸运的是,面向对象程序设计语言特别适合支持这样连续的修改,由对象创建的边界是防止结构被破坏的保障。面向对象程序设计语言还允许我们做大幅度改变而不引起代码的全面动荡,这在过程型程序中似乎太剧烈了。事实上,支持进化可能是OOP的最重要的好处。
借助于进化,我们创建了近似于我们所要创建的程序,然后进行检查,与需求比较,看哪些地方有缺点。随后回头看,重新设计和重新实现程序不能正确工作的部分,改进它[3]。在得到正确解决方案之前,可能实际上需要几次解决这个问题或问题的一个方面。(对设计模式的研究在第2卷中描述,对此阶段非常有用。)
进化还发生在我们建造系统时,开始它好像符合需求,以后又发现它实际上不是想要的系统。当看到这个系统运行时,我们发现实际上想要解决的是另一个问题。如果我们认为这种进化将会发生,则应该尽快地建造第一个版本,这样可以发现它实际上是不是想要的系统。
也许,需要记住的最重要的事情是,按默认情况(实际上是按定义),如果修改了一个类,则它的超类和子类都仍然正常工作。不要害怕修改(特别是,如果我们已经有内部的一组单元测试,验证了修改的正确性时)。修改不一定会破坏程序,结果的任何改变都将限定于子类和/或被改变的类的协同者。
[1]进化的一个方面在Martin Fowler的专著《Refactoring:improving the design of existing code》(Addison-Wesley,1999)中做了介绍。需预先警告,这本书的例子全部使用JAVA编写。
[2]这一术语在第2卷的“设计模式”一章中研究。
[3]这是有些像“快速生成原型”,先建造一个快而稍差(qwick-and-dirty)的版本,然后研究这个系统,再丢弃这个原型并正确地建造它。快速生成原型的麻烦是人们不丢弃这个原型,而是在它上面建造。与过程型程序设计中缺乏结构相结合,这常常会产生混乱的系统,使得维护费用提高。