经常在TDD训练营中有学员提这个问题:学了TDD,在项目上也没法落地,为什么TDD很难在项目上推动?
TDD本身就是一项具有争议的实践,但凡不是一个极限编程践行者,很难坚持贯彻实践TDD,原因有很多,如果"不负责任"的回答可能是:
- 自身技能不熟练
- 项目不允许,因为TDD会影响交付
- 系统很难写测试
- ......
原因说的再多,导致难以推动只因为存在一个问题 -- 一旦你用了TDD,就会阻碍交付,即让你交付的速度下降。 如果没有影响交付,就不会有任何实质性的问题。
第1种原因,就没什么可说了,技能不熟练,用新的东西,速度肯定会变慢,而且还容易出错,原本项目就紧巴巴的,肯定会拖慢交付速度。但这个也是相对较容易解决,只是时间的问题,多花点业余时间练功就好。我说相对,确实是相对的,相对你所在项目交付节奏的紧张程度。越紧张,你就越难有时间去练功和项目上运(试)用(错),越没有时间练功,你就越没法好好运用。所以当你所在的项目紧张到自己对完成交付缺乏信心的时候 ,你就不愿意投入时间学习,而想用这个时间来加班工作。如果没有超过临界值,你需要锻炼的主要有以下几个方面:
- 分析性思维,能够更加高效地理解问题,拆分问题
- Clean Code sense,能够花同样的时间写出更简洁的代码
- 单元测试,能够写出有效的单元测试
- 设计思维,能设计出符合业务模型的代码。比如OOD,Simple Design
- 重构技巧,能够有效的阻止代码腐化,持续改进设计
- 手速(快捷键),编写同样的代码,花的时间更少。
第2种原因,得分两种情况。一类是项目紧张到对新东西没有丁点容忍,实在没法给新人尝试新东西的空间,这种项目你可以做完后考虑换一换了。另一类是项目其实还是有空间的,只是因为大家都在依照本能开发,没有测试,很多人肉测试和返工的花销。在这种情况下,你可能觉得要上洗练套餐了(洗脑+练兵)。其实,最重要的是,你自己要先把基本功练扎实,让自己能够在有限的时间内完成从Tasking到TDD的连招,做好表率,然后证明TDD缩短了DoD(Definition of Done)的周期,并证明自己写的代码Bug率更低。拿着数据,再上洗练套餐。当然在这种情况,你要付出别人更多的努力,你要在狭缝中杀出一条生路,所以唯一的捷径是自身的基本功修炼之路。话说,项目为啥不允许TDD?实际上是因为担心会影响交付进度,如果能扭转这个因果关系,项目会管你用不用TDD吗。
第3种原因,确实有那那么一种系统,自诞生就是一个遗留系统(Michael C. Feathers在《修改代码的一书中》提到:遗留代码就是那些没有编写测试的代码)。由于系统很难写测试,就别谈TDD了。如果排除了上述两种原因,那么这种原因极大可能是系统架构设计出了问题,不是没有分层,就是层分多了;不是层分多了,就是层分错了;如果都不是,那就是层与层的依赖关系混乱了。如果架构的设计出了问题,你就很难对系统或者某一层去写测试。就好比:
- 系统没有分层,是一个大单体,不知道从哪里写测试,感觉哪里都要测,又感觉哪里都没法测。
- Controller层依赖了Use case层,Use case依赖了Domain层,Use case依赖了Infrastructure层,Controller又依赖了Domain,Domain又依赖了Infrastructure层,感觉要测试Use case,但各种复杂依赖。
TDD很难推动的原因有很多,可以尝试先解决内因(自身基本功),内因是更可控的。但解决了内因,也不一定能克服外因,外因有很多种情况,不知道你遇到了哪种?