上篇文章说了QA与QC的区别,以及一种不太好的流程所造成的浪费,这篇对我所在团队的状况进行反思。
为什么这么多bug?
1个月200多个,按工作日平均下来1天10个,触目惊心。我认为原因很多,列举如下:
- 环境。在进度第一的观念下,代码库中渐渐充斥着设计拙劣、充满陷阱的代码。殊不知慢就是快,而表面上的快实际上严重拖慢了团队的脚步。造成的结果不仅bug多,而且被fix后,不知哪天又冒出来了。
- 程序员习惯。一个团队中的坏习惯比好习惯更容易传染,如果代码中到处都是不规则的命名、长函数、无用的代码、与代码不一致的注释、圈复杂度好几百,那么如果不是有特殊的动力,谁还有心情去写干净的代码?
- scrum-but。比如,sprint结束没有demo,没有product backlog,没有user story。关于scrum-but,这边有ppt下载。好现象是,这些状况有很多改善。
- 没有XP实践。现在有了code review,及其偶尔会有pair,但还非常不够。没有pair过的人是体会不到它带来的代码质量和产量的提升的。也很少有unit test,有不少test都不是“unit” test,因为他们依赖于数据库,或者外部文件,他们很少被运行。另外有些地方根本没办法写unit test,因为一个类的一个方法做了太多事,不够SOLID。
- 没有持续集成。只有daily build,没有local build脚本。很多次发生代码库里的代码不能通过编译,却很久之后才被发现的情况。
- 组织结构的问题。daily build是专门的CM部门维护,CM部门的人不属于我们的Scrum团队。而Scrum应该是one team,一个跨功能的团队。
- 项目结构的问题。整个项目按模块分成几个solution,而每个solution都包含公用的十几个project。如果按solution来 build,势必造成公用project的重复build。CM的daily build脚本是怎么处理的呢?它不build solution,而是依一定顺序,build所有的project。所以如果dev增加了一个project,脚本就必须改。——这样的脚本,实在没有把它拿来当local build脚本的心情。
- VSS。我们是分布式团队,VSS服务器在上海,外地团队获取代码的时间要数个小时,所以他们几乎不获取。他们只在每周,由某人获取他们团队正在工作的某个solution(不是全部),然后其他人从他那copy。团队的代码永远都是过时的。这样的情形延续了两三年,在最近终于转向了SVN。 SVN不是目的,只是Check in dance的基本前提。
- 流程。那么多bug,可是我们应该责怪的不是团队成员,而是流程。在上篇文章开头提到的流程,真实的发生在我们团队。
kanban
我们以Scrum为框架“使用”敏捷已经近三年了,但是“使用”一词只能加上引号。因为很长一段时间,都没有user story;没有代码集体所有;QA 和Dev以及Dev之间交流太少……为了强化团队成员在开发期间的交流,也为了促使PO写出更小的story,我们前一阵做了一个尝试:尝试不再拆 task,领到story后直接做,把拆task时的讨论,从plan meeting延后到真正写代码的时候,避免写代码时单兵作战。——其实这时非常适合pair,可惜……。(有奖竞答:在中国的软件团队实行Scrum,最大的障碍是什么?)
没有task,带来一个相关的改变,就是scrum board的改变,我们引入了kanban的一些理念,改变后的白板如下:
白板很简单易懂:story就是plan meeting上团队commit的所有story。dev开始写代码时,移到development一列的ongoing,同时QA设计test case。代码完成(一般QA的case也完成)则往右移到done。然后QA开始测试时,把它移到verify中的ongoing,所有test case通过,则往右移到done。最后PO检查一下,如果没有问题,则放到最后一列Live!另外,development和verify都有WIP的限制,分别取得是dev人数+1,QA人数+1。
一切很完美,直到bug的出现:QA在verify的时候,如果有bug怎么办?而且如果这是development列的WIP已经达到限制了,有bug的story怎么办?把development列的1个story往左移,再把有bug的story从verify移回到 development列?这是个好的开始。我的意思是,kanban的一个目的达到了——它把潜在的问题可视化了。
既然问题出现,就应该解决。回想上篇文章的内容,解决办法很简单——既然有QA的test case,那么在verify的阶段,为什么要出现bug?dev写完一个story,在没有通过test case检验的时候,就把它扔给QA,同时自己去开始编写下一个story的代码。——这是典型而常见的错误流程。为什么在development的时候,就把“代码写完+case通过”成为done的条件呢?是的,但就这个改变来说,bug不会少,但是bug的发现会提前,并且减少了dev和qa之间的往返。
因此我的想法是把白板改为如下:
当然白板的微调只是表象,需要调整的是流程,是观念,是test first的理念。
什么是TDD
TDD在很多人眼里是可望不可即的,它需要很高的技能,其实这样想的人也许对TDD有些误解,很多人以为TDD的T只是Unit Test。其实不是。TDD是测试驱动,这里的测试包括unit test,也包括验收测试。在scrum中,每个story都有“验收条件”,QA正是以此为蓝本来设计test case,设计出来的test case其实就是story的“验收测试”。那么我们以此“验收测试”来驱动我们的开发,不也是TDD吗?虽然我们还写不出自动化的验收测试,我们不会用 FIT或者Story Teller或者Spec Flow……,但是,如果QA在设计test case时即与Dev保持沟通和思想碰撞,用test case来指导我们的代码编写(而不是在代码完成后用来“发现”bug),我认为,这也是一种TDD,是最廉价却同样有效果的TDD。在练习TDD技能的同时,不要忘了TDD的一种简单定义:TDD is a technique where teams use short development iterations based on pre-written test cases.
怎么样减少bug?
文章开头列出的那些问题,如果都解决了,bug是不是就减少了?也许,而且那只是我看到的问题,也许是对,也许是错。重点是团队养成反省,发现问题和学习的习惯。