本文主要目的是向大家展示基本的TDD思考过程,以及带来的效率和质量提升,帮助大家树立对TDD的兴趣和信心。
背景
我所在的敏捷教练团队开发了一个看板系统,用来透明化各产品团队的研发过程,其中一个需求是显示团队每个冲刺的燃尽图,需要从Jira里获得冲刺燃尽图数据,在看板系统呈现。这个功能已经由别的同事使用NodeJS实现过一遍了,当时花了近两周时间,但是存在几个顽固bug,现在找不到人维护了。为了解决这些BUG,同时对比一下采用TDD的开发方式时效率能提高多少,我决定用TDD的方法来实现这个功能。最终仅用两天的时间就完成了功能的开发和测试,证明TDD确实能大幅提高软件开发效率和质量,过程如下:
1. 整个过程大概消耗两天时间(需求分析、人工测试、重构),编码时间小于8小时,没有加班。
2. Sonar技术债:0
3. 单元测试覆盖率>90%,由于使用了lombok插件,所以一部分覆盖率统计不准,实际是接近100%的。
过程回顾
一、进入TDD过程之前需要完成 需求理解和细节确认(3小时)
严格来说这步工作不属于TDD实践过程,但是这步缺是必不可少的,因为不管开发什么功能在现有条件下尽早正确理解需求是最基本条件,如果需求都搞不清,那用什么方法也没用。
这一步主要完成了如下工作:
1.首先分析jira的数据库和页面,查找数据来源,最终找到一个HTTP接口,通过分析接口返回的数据,确认可用通过这个数据计算得到燃尽图数据,数据来源解决了。
2.分析接口数据,确定数据内容及如何使用,经过分析,发现数据内记录了与当前迭代相关的所有故事的变化日志信息,用户每执行一个操作就产生一个记录,而且数据时间戳是没有排序的。
3.建一个测试JIRA项目,模拟项目操作过程(包括异常情况),每操作一步查看接口返回数据的变化情况,记录下来相关特性,作为后面开发和测试的依据。
4.确认最终需要输出给界面的数据格式要求。
复盘分析:
这个过程是后续工作继续的基础,通过对需求的分析初步确定了可行性和详细范围,确定了验收条件。如果你是基于敏捷开发方法的话,这步工作相当于我们在计划会之前完成的对用户故事进行了讨论与分析,澄清验收标准的过程,需要注意如下事项:
1.在后面开发过程中这步工作还需要反复来做,这步越充分,后续工作会越高效。
2.讨论过程中确认的所有细节都尽量落到纸上,例如写到故事卡后面。
3.如果是比较复杂的需求需要有个二次确认过程,类似于一个故事开始开发之前的Kick Off,避免带着疑问开始编码。
二、初步构思,拆分待办列表(2小时)
从这步开发我们才真正开始了TDD过程。
实际上以上两步最初都是列到本子上的,先画一个实现思路的草图,然后根据已经掌握的需求细节列出一个初步的待办列表,这样做我感觉是最高效的,另外我认为TDD只是提供了一个节奏和快速反馈机制,并不是一种设计方法,只是应用TDD并不能带来良好设计的代码,所以实践过程中该有的设计思想还是要坚持。
复盘分析:
这是整个过程的关键也是很多人觉得困难或者最容易忽略的一步,在这一步需要注意:
1.TDD也需要全局思考,通过对要解决的问题进行分析,确定基本实现策略后再开始TDD过程,TDD的小步快跑并不是盲目的,需要在有一个大方向正确的前提下来开展,越是复杂的系统这一步越必要。
2.注意坚持简单设计的原则,够用就好,避免过度设计,好的架构是在思路正确的前提下演进出来的,不是一步到位的,开始时候想太多反而会影响实现思路和实现效率。
在拆分需求和分解待办列表时需要注意:
1.实现思路决定了后面的问题分解思路,如果还处于摸不到头绪的状态要先想清楚再继续,实现思路确定后再进行问题的拆分效果会更好。
2.拆分过程主要通过分析问题边界、输入和输出过程来进行。以本功能为例,整个过程可以描述为首先解析输入的原始JSON,构造出排序后的事件日志集合,然后对事件日志进行回放,冲刺对象基于回放过程记录剩余故事点变化数据,回放结束后输出剩余故事点的变化列表就可以了。因此我们拆分时候就可以按照解析和回放两个维度进行拆分,解析的输入是原始JSON,输出是事件集合,回放过程的输入是事件集合输出是燃尽图数据。然后再按照“输入-过程-输出”的思路逐一进行拆分,最终得到待办列表。
3.对于待办列表需要注意列表描述要明确,因为这个是最终指导我们写测试的输入,所以需要包括具体的输入和预期输出情况,例如本项目中如下这个写法就是错误:“未完成问题移除后会影响燃尽图和计划外故事点;”,未完成问题移除后是如何影响燃尽图的?如果未完成问题未估算故事点是否有影响?估算了故事点的是会导致燃尽图上升还是下降?这些信息因为我了解上下文,所以写代码时候也会考虑到,考虑如果给一个不熟悉上下文条件的人来维护后续代码,肯定是没法看懂的。
4.随着对需求理解和实现思路的进一步深入理解,这个列表也是一个动态更新的过程,需要不断把新的待办添加进来,把失效待办移除。这一步可以通过在源码文件里通过TODO标签来记录。
三、编码实现(小于8小时)
复盘分析:
四、加入验收测试(1小时)
在以上实现过程中,我发现总还是有各种特殊的项目有一些骚操作是意料之外的,为了便于后续维护代码,我决定加入一组验收测试代码,用于将Jira上存在的多个存在特殊情况的项目的燃尽图数据与程序输出进行逐一对比,确保程序处理逻辑没有偏差,作为验证当前完整处理逻辑的手段。
复盘分析:
这一步严格来讲不是测试驱动开发的一部分,可以看做是验收测试,但是这个又与ATDD不一样,是在上面待办都完成后为了确保以上实现的完整性而加入的,主要目的还是想通过这部分测试确保程序输出与JIRA输出数据完全一致。
总结
到现在为止程序已经运行一个多月,目前是0缺陷。
听说TDD实际已经很多年了,但是一直抱着怀疑的态度,认为要做TDD需要良好的架构和团队个人能力来支撑,自己日常接触的团队没有办法达到这个水平,也没有去学习和尝试。真正学习和实践之后发现入门并开始实践并没有那么难,只要加以刻意练习,可以在短时间内得到很大提升,而且可以明显感受到开发效率和代码质量比凭感觉直接写业务代码时候有极大提升,相信通过更多的练习之后能带来更大的改变。还在犹豫和观望的你,不如尽早动手,一起提高我们的开发效率和开发质量吧。
更多干货欢迎关注 公众号 @敏捷新视界