我们平时开发的流程大致分为两个步骤:确定需求,编码实现。如果分得再细一点,可以分为n个步骤:提出需求、确定需求、编写需求文档、数据库建模和对象建模、编码、集成测试和验收测试。编码的过程又可以分为n个步骤:编写功能代码,单元测试。虽然这种流程不算是RUP,但我觉得却是向着RUP进发。
但从《测》一书中,我没看到作者要求在开发中具备完整的文档,看第一遍的时候我是觉得作者是从编码中得出需求的,但看第二遍的时候我又否定了自己的想法。《测》的作者Kent Back拿了一个汇率计算的例子向我们演示如何TDD,在例子的第一次单元测试失败后,我们可爱的MR.Kent已经得出了汇率计算的所有需求,这时我释然了,TDD应该也要结合实际嘛,然后需求真的是从开发中驱动出来么?不可能,这样的话还要客户干嘛?这是我当时的想法。
如果到了这里已经算是解开了疑团,我也没必要写这篇东东了,下面我借花敬佛,通过TDD所包含的步骤开打开话匣子。
TDD可以分为三步:
1、 写一个不可以工作的测试,一开始这个测试程序甚至不能编译。
2、 尽快让这个测试程序工作起来,为此可以在程序中使用一些不合情理的方法。
3、 重构,消除重复设计,优化设计结构。
为什么一定要先写一个不可以工作的测试?而不是先写一个不可以工作的程序?为什么一定要由测试来驱动开发,而不是先开发,后测试?先写Test Case后写程序的方法,会不会导致开发效率降低?
这些疑问一直缠着我很久了,虽然不致令我寝食难安,但让问题存在了这么长的时间是一位coder的耻辱。结合在不久前景德镇的会员中心改造这一需求和几晚的思考,一些云雾已经渐渐被拨开。
为什么一定要先写一个不可以工作的测试?而不是先写一个不可以工作的程序?
这里的测试并非普通的测试,甚至跟我们想像中的测试是完全不同的,它是对需求的理解。TDD要求我们在测试前写一个测试清单,这更像把需求整理出来。不过TDD根本没要求我们把测试做得像验收测试那样详细,TDD要求能清楚表达需求就行了。
为什么一定要由测试来驱动开发,而不是先开发,后测试?
TDD有一个标准,就是在没有测试的情况下,决不编写任何程序代码。TDD提倡小步跑,在开发过程中要考虑很多东西,包括代码的正确性、可扩展性、性能等等,很多问题都是因为复杂性太大导致的,这导致了很多时候“设计过度”,因此TDD的每一步都是适可而止的,今天的事今天解决,明天的事明天再说。
先写Test Case后写程序的方法,会不会导致开发效率降低?
这里是我最大的疑问,不过没实践过因此没任何发言权。我们重温一下测试驱动的三步曲:
1、写一个不可以工作的测试,一开始这个测试程序甚至不能编译。
2、尽快让这个测试程序工作起来,为此可以在程序中使用一些不合情理的方法。
3、重构,消除重复设计,优化设计结构。
怎样能能使用这个测试程序尽快地工作起来?以下是《测试驱动开发》一书中的摘抄:
1、 伪实现,可以直接返回一个常量。
2、 显明实现,将真实的代码键入。
3、 三角法,在不确定的时候可以由几个方面抽象出共同的事物,类似已知三角形任意两边可以得出第三边。
4、 可以使用复制粘贴等方法让你的程序尽快的工作。
5、 千万别忘记了重构,这是很重要的一步,在重构前写出你希望拥有的测试。
可能大家和我有一样的同感,这什么伪实现很扭扭捏捏嘛,这步伐也太小了吧,不过Kent Back说了,用什么样的步伐来跑,决定于你的感觉和经验,跟着感觉走准没错。
写到这里好像似乎可以结束了,不过这两晚我重温了《敏捷软件开发:原则、模式和实践》一书后,脑子里又塞满了一堆的问号。
XP是这样给自己定义的:
1、个体和交互 > 过程 (这里主张团队沟通,理解)
2、可以工作的软件 > 面面俱到的文档 (这里与我们背道而驰,有疑问)
3、客户合作 > 合同谈判 (需求在不断变化,理解)
4、响应变化 > 遵循计划 (开发过程不可能一成不变的,理解)
5、初期交付的系统中所包含的功能越少,最终交付的系统质量越高。(赞成)
下面这些更难以理解:
1、 XP缺乏明确的设计阶段(怪不得TDD是XP最著名的一个开发方式,但如果团队的成员拿不准方向咋办?与目标越离越远咋办?)。
2、 在给新的团队成员传授知识方面同,最好的两份文档是代码和团队(不是每个人的代码都写得清淅明了的,不是每个人都善于沟通的,这里会不会太理想化了)。
3、 许多团队因为太注重文档而非软件,而导致失败。(会不会夸大其词?)
4、 先在测试中陈述你的意图(这就是TDD吧)。
5、 XP没有全局视图或者全局视图不明确,这里存在着与第一点相同的疑问。