1.10 极限编程
我从研究生时开始就断断续续研究过分析和设计技术。极限编程(eXtreme Programming, XP)的思想在我见过的方法学中最为激进也最令人愉快。在由Kent Beck编写的《Extreme Programming Explained》(Addison-Wesley,2000)[1]一书和在Web站点www.xprogramming.com上可以找到它的历史。
XP既是程序设计工作的哲学,又是做程序设计的一组原则。其中一些原则反映在新近出现的其他方法学中,但我认为,有两个原则最重要、贡献最大,即“先写测试”和“结对编程”。虽然Beck强烈坚持全过程,但他也指出,如果只采用这两项实践,就能极大地改进生产效率和可靠性。
1.10.1 先写测试
测试传统上被归于项目的最后阶段,在“万事俱备,只欠肯定”之后。这意味着它的优先级很低,专门做此工作的人没有足够的地位,甚至可怜兮兮地只能在地下室里干活,不算“真正的程序员”。测试组对此的反应是,穿着黑色的衣服,当攻破了某个程序时就兴高采烈(老实说,当我攻破了C++编译器时我也有这种感觉)。
XP革命性地改变了测试的这个概念,将它置于与编码相等(甚至更高)的优先地位。事实上,我们需要在编写被测试代码之前写测试,而且这些测试与代码永远在一起。这些测试必须在每次项目集成时都能成功地执行(这是经常地,有时一天几次)。
先写测试有两个极其重要的作用。
第一,它强制类的接口有清楚的定义。我经常建议,人们设计系统时会把解决特定的问题的理想的类,作为工具。XP的测试策略比这走得更远,它准确地指明这个类看上去必须像什么,对于这个类的用户,这个类准确地如何动作。用确切的术语,可以写所有的文档描述,或者创建所有图表,描述一个类应当如何行动和看上去像什么,但是什么都比不上一组测试真实。前者列出的是期望,而测试是由编译器和运行程序强制的合约。很难想象有比测试更具体的类描述。
当创建测试时,我们被迫要充分思考这个类,常常会发现所需要的功能,而这些功能可能会在思考UML图、CRC、用例等过程期间漏掉。
写测试的第二个重要的作用,是能在每次编连软件时运行这些测试。这实际上让编译器又执行了测试。如果从这个角度观察程序设计语言的发展,就会发现在技术上的改进实际上是围绕着测试开展的。汇编语言只检查语法,而C增加了一些语义约束,能防止程序员犯某些类型的错误。OOP语言强加了更多的语义约束,可以把它们看成是某种实际形式的测试。“这个数据类型的用法合适吗?这个函数的调用合适吗?”这些都是由编译器或运行时系统执行的测试任务。我们已经看到了在程序设计语言中加入这些测试的成效:人们能用更少的时间和劳动写更复杂的程序,并使它们运行。开始我不理解为什么能有如此成效,后来认识到,这正是测试的作用。如果程序员写错了,内部测试的安全网就告诉他有问题,并指出在什么地方。
但是,由语言设计提供的内部测试只能做部分的工作。有时,我们必须自己动手,增加其余的测试,形成配套(与编译器和运行时系统协作),验证程序的一切。正如编译器能陪伴帮助我们一样,我们也希望其他的测试也能从一开始就帮助我们。这就是为什么我们要书写测试、并在每次系统创建时自动地运行它们的原因。我们的测试就变成了这个语言提供的安全网的扩充。
在功能越来越强大的程序设计语言中,我发现可以更大胆地尝试更多易错的实验,因为我知道高级语言功能会帮助排除错误,避免浪费时间。XP测试机制对于整个项目的作用也是如此。因为我们知道测试始终能捕捉我们引进的任何问题(当需要时我们有规律地增加新的测试),所以当需要时可以做大的改变,不用担心会使整个系统混乱。这真是太强大了。
[1]本书的中文版已由人民邮电出版社出版。—编辑注