软件开发过程有一个很自然的比喻:建楼房,要画图纸、搭架构、砌砖头。这个比喻大体说得过去,问题是,这个“砖头”绝非普通的砖头,具有以下特性:
一、每一块都由手工制作;
二、每一块的材质、形状、尺寸都不同;
三、任何一块有问题,在某种天气下,房子会漏水;如果1%甚至1‰的砖头有问题,房子会到处漏水;更严重的是,一块或多块砖头有问题,还可能造成房子在某些时间倒塌。
正是因为“砖头”的上述特性,所以存在两个80%:软件的质量,80%依赖于代码;软件的开发成本,80%用于编写合格代码,请注意,是“合格代码”,不是“代码”,后期的测试和排错,也是编写“合格代码”的组成部分。即使两个80%不准确,改为70%,甚至60%,决定软件质量和开发成本的大头,也仍然是编码。不重视编码过程的改进,提升质量和产能就失去了最主要的着力点,必然会感觉什么措施都效果不明显。
如果建楼房的砖头也具有上述特性,相信任何一个建筑商,都会绞尽脑汁,找出一次性做出合格砖头的办法,而不是等到楼房建起来再查找和修补有问题的砖头。
软件开发,有没有一次性编写合格代码的方法?有,例如TDD。TDD是敏捷开发的核心实践之一, Ruby On Rails的创始人DavidHeinemeier曾说,当年它打开了一扇门,让自己看到了高质量代码的全新世界。
然而,TDD太难了,而且为了解决可测性问题,需要做很多额外工作,例如为了支持Mock而做的很多重构。David Heinemeier近日发表了一篇文章:《TDD已死,测试永生》,痛批TDD过于偏重单元测试,过于琐碎,会使系统同许多中间层、中间对象组成,带来复杂臃肿的架构。他明确声明自己将放弃TDD。
如果对TDD进行改进,消灭它的主要成本,并放大它的效益,就得到了一个大幅提升代码质量、大量降低开发成本的开发方式,这种开发方式,就是easy TDD,简称eTDD。
eTDD如何做到消灭TDD的主要成本、放大TDD的效益呢?答案是利用工具:由工具完成苦活、脏活、重活;由工具描述程序行实现可视编程。
苦活、脏活、重活包括:编写测试驱动、编写桩代码、编写Mock、覆盖统计、找出遗漏用例、编写测试报告,并避免仅仅为了单元测试而做的重构,总之一句话:除了测试数据需要人工设定外,其他都由工具完成,这样,就消灭了TDD的主要成本。
可视编程则显著放大TDD的效益。可视编程就是编写代码时,可以随时察看程序行为。程序行为,就是在什么输入下,会执行哪些代码,会产生什么输出。单元测试的输出可以完整描述程序行为,使程序行为可视,这是极宝贵资源,TDD忽略了这一点,甚为可惜。利用可视编程,程序员写几行代码,就可以看看程序会做什么,从而验证思路、发现错误、激发灵感。对于比较复杂的程序,用可视编程编写合格代码的效率,是传统方式的4、5倍,同时,还能降低编程的劳动强度,保护程序员的健康。
人类生产力的提升,绝大多数依赖工具的进步,软件开发也不例外。编程是高技术工作,人才成本很高,而且会越来越高,一名月薪1万的程序员,公司要付出的实际成本为1.5万至2万,折算成小时成本,大概是100元,即手工编写测试代码,1小时要付出100元,而这种工作完全可以由工具代劳。eTDD将麻烦的事情交给工具,避免了以手工为主的TDD所产生的高成本,更重要的是,eTDD简单易行,不用考虑让人头疼的“可测性”问题,因为解决可测性问题,是eTDD工具的基本功能。eTDD可以在项目周期的任意时段引入,还可以部分引入,例如,只对较底层或较重要的代码使用eTDD。总之,只要使用合适的工具,eTDD很容易实施,效果立竿见影。
eTDD与传统方式对比实验,以及实际开发任务实验,可以证明:eTDD使编程产能翻二番,当然,这是指单纯编写合格代码的产能。除了编写代码,程序员的工作还包括:对技术难点的研究、查阅文档、沟通、开会、写文档、发呆等等,这些时间,eTDD当然不能产生作用。一般来说,如果没有大规模的需求变更,eTDD缩短开发周期30%是可以预期的。这里说的开发周期并不是“计划”周期,而是“实际”周期,例如,计划三个月完成的项目,实际周期往往是六个月,如果用eTDD,则可以四个月完成。缩短开发周期只是eTDD的次要效益,eTDD的首要效益,是保证代码质量。