作者:黄承开

这两天读到了一篇关于TDD的专栏文章如何说服你的同事使用TDD,正好前段时间也有思考相关的问题,有一些想法正好分享一下。

当然前述文章本身的质量还是很高的,旁征博引,但是看过这一类文章的资深一些的工程师一定会产生一个疑问,既然利弊分析了那么清楚,为什么TDD没有成为一种除了在大型开源组织和框架类项目之外(这两者在所有的软件项目中的比例是非常低的)被广泛采用的开发技术?要知道从事这个行业的大部分都是“聪明人”,如果一种技术真的那么好而没有被广泛的认可,那岂不是大家都是糊涂蛋?

首先,我个人经历和观察到的软件开发活动是围绕结果展开的,这个结果大部分情况下有可以量化的商业价值,也就是说无论任何类型的开发技术最终是否能流行取决于是否能以合理的成本提供这种价值,而不同的开发技术之间的替代都是基于这种性价比的评估。我无意于逐条的去批驳前述文章的观点,因为这些观点本身并没有任何错误可言,提高代码质量进而提高软件质量肯定是政治正确的,而这些仅仅只是复杂的软件开发活动的一个方面。

我把TDD是否能流行归结于以下几个方面的评估:

  1. 投入资源,实施/实践这种方法需要消耗多少的资源?
  2. 软件的类型,复杂度和成熟度,是一个应用还是一个框架?这个软件可能有多少个特性?目前已经开发了多久?预计还需要开发多久才能完成?是否会继续的迭代?
  3. 团队成员的技术能力,团队中经验丰富的工程师比较多还是新手工程师比较多?
  4. 交付价值,采用了该技术之后,能为产品提供什么样的价值?

投入资源

坦白讲TDD本身并不算很复杂的技术,学习曲线也没有很陡峭,但是掌握粗泛的写测试用例的方法并不能像你想象的那样提高软件质量,针对各种实际业务的case去写能实际提高代码质量的测试代码是一种成本相当高的行为(甚至需要hack三方依赖的代码),我知道有一些团队甚至专门让资深的工程师(一般意义上成本更高)负责写测试用例。

软件的类型,复杂度和成熟度

软件本身的性质是决定TDD是否能流行的最关键因素,TDD不是什么便宜的技术,而TDD代码依附于实际产生作用的业务代码,但本身不是并不是产品的一部分,这意味着如果这部分业务代码如果被被删除了,那么TDD代码也失去了价值,也就是投入的资源都白费了,坦白讲这点非常令人沮丧,但是实际上这种过程在一个互联网或者说外包项目的开发过程中是无法回避的,甚至在项目的早期阶段是主要过程。反之,框架级别的项目和大型基础开源软件在主要版本的开发过程中很少遇到类似的困扰,另外此类项目的代码一般都广泛存在于大部分项目中,提高代码质量的边际效益极高。当然这种分类本身是不精确的,只是帮助大家判别软件本身的性质。

团队成员的技术能力

一个资深工程师,不使用TDD几乎一定可以比使用TDD更快的完成特性的开发和交付,从产品质量来讲却不一定有显著的提高。因为决定产品质量的代码是否正确绝大部分取决于对业务的正确理解和技术的正确运用,而资深工程师本身在这两方面一般来讲已经合格,使用TDD并不能直接起到什么提高。对新手工程师来讲,TDD可以帮助理解业务,但是额外编写正确测试用例代码的成本是否值得需要单独评估。

交付价值

这里我觉得可能是会产生争议的地方了,我认为产品价值的确认并不是直接通过业务代码,更不要说依附于业务的TDD代码,而是最终用户,代码是一种载体,如果用过河比喻的话,如果你的用户是行人,那么独木桥就足够了,如果是自行车,一座石桥是个好选择,如果是汽车,那么铁桥可能是必须的。当然铁桥可以走行人和自行车,并无不妥,但是铁桥更贵,需要更长的建造时间。在我经历过的项目中这么奢侈的情况屈指可数,不幸的是,似乎我所了解的其他人的开发活动也总是被资源不足的阴云笼罩。一般来讲,代码质量对产品价值的提升,在短期内总是被高估,长期被低估,在工程师群体内被高估,工程师群体之外被低估。脱离产品谈代码这个问题上我的经验教训颇多,也许我会另外花时间写篇文章谈一下。

总结

我个人觉得TDD可以看作一种保险,是否需要为你的项目或者团队购买这种保险取决于以上四个方面(也许更多?)。这些结论都是站在一个全面了解TDD技术的团队负责人的立场上做出的,屁股决定脑袋,对于团队中的其他人来讲会存在不同的结论。另外这种评估的方法也可以适用到一般性的软件开发方法/思想/指导原则上。

后记

坦白讲我并不认为TDD那么差劲以至于无法流行,TDD本身就源于实际的软件开发活动的经验积累,问题在于推广TDD技术的主要“布道师”或者说我所知道的唯一强制使用TDD的组织成员,这些人通过一些恐吓性的语言,类似于“不用TDD就无法写出高质量的代码”,翻来覆去的百度百科词条式的内容,“使用TDD能给你带来12345等好处”,自我催眠式的拙劣推销员一样的话术,“如果不是用了TDD,xx项目简直无法开发出来”,怎么说呢,充满了原教旨主义者气息让我或者说一部分人产生天然的抗拒。软件开发这个行业很年轻,还在快速发展中,技术和理念本身都是基于积累的经验不断的改进和变化的,对个人来讲不能因噎废食,除了要根据自己自身的情况去客观评估得出结论外,我个人也提供一些额外的建议,TDD提供了丰厚的代码资产,思考如何利用这些资产来提高开发效率是一个很有意思的topic,另外思考利用TDD技术结合devops加速deploy也是一个可以切入的点,最后我甚至觉得如果用AI来写代码的话,似乎TDD也大有可为?