“To err is human”
在过去相当长一段时间内我都在一个负责进行项目维护的团队内工作。团队的特殊之处在于我们从来不开发新功能而是负责解决每天上报的线上问题。这些bug 无奇不有,从无法打开页面到数据奇怪丢失,麻木早已经替代焦虑成为了我们面对 bug 时的主要情绪。
但我时不时地抱怨依然是:为什么 bug总是在发生。
缺陷早已在丰田生产系统(ToyotaProduction System)中被标注为浪费之一。没有人希望看到 bug,我们不想,客户更加不想。但我们似乎都不愿承认的一个事实是 bug是代码的副产品而已。如果我们选择接受编码不过是人思维活动的一种形式与思考无异,那我们也就必须接纳人性的缺陷在代码中自然也不会缺席,恰如硬币的正反两面。
反过来说,如果你对 bug采取的是零容忍的态度甚至不惜把此写入 KPI中,它也未必会带来正面效应,因为自此开始,没有人会愿意重构,没有人会愿意引入新的技术方案,道理非常简单:改动越多风险越大——这是某年发生在我所属团队的一次亲身经历。
所以我们并非面临的是 bug去或者留的选项,而是多与少的问题。
摆正质量
在 MoSCoW方法论的框架下,我们通常可以将功能的优先级划分为四类: Must Have, Should Have, Could Have 以及 Won’tHave,如果把质量也作为功能的一个维度选择落入这四个区间之一的话,它一定不会在 Must Have 这个范围内。因为人们既不会因为没有 bug而选择长时间地使用一款应用,也不会因为存在 bug而成为转投它竞争对手的理由。我们必须承认这样一个事实:质量永远也不是商业的核心竞争力,这也暗示着:
- 质量缺陷是可以被容忍的
- 质量被分配得到的资源永远是有限的。
前者并非我们的一厢情愿,在互联网产品的高性价比和快速迭代的商业逻辑下,用户对产品质量的预期已经被规训到一个非常「理想」的状态
而后者更为关键:我们应该如何最大化利用有限的资源去提升质量?如果你所在的部门也有机会组建一支类似于本文开头团队,那不妨考虑一下这个建议:用资源换取更多的人员加入这支团队怎么样?
原谅我用一个粗俗的比喻来解释为什么这么做行不通:我们换来的只是擦屎的速度,对造屎的人产生不了任何影响,效果甚至会适得其反:考虑到总有人为他们收拾残局,我们的善后工作做得越好,他们越是会肆无忌惮。
但这是当下大部分公司的现状:如果线上问题激增,是不是QA 工作不到位?我们似乎倾向把编码和测试的界限划分得一清二楚,从人员到职责到工序都是如此。而质量问题从编码中来,却想从测试中寻找解决之道,这与刻舟求剑无异。
铺垫了如此之多我想表达的观点依然是老生常谈:质量内建,以及最近几年我们常常提倡的测试左移。 至于什么是质量内建和测试左移,并不在这篇文章的范围内,你在网上可以找到大量的专业文章来介绍他们
质量的成本
现在我们必须回答一个核心问题:谁该对质量负责?最官方的答案是每个角色,我们可以列举出产品经理没有全面地对功能做验收,QA没有把控好质量关等等。但假定此刻我们必须指定一人将他五花大绑起来祭天,为的是有人需要为上一个让人焦头烂额的bug 负责,程序员绝对是不二之选。
但程序员死也不会瞑目的。
如果你是团队经理,你发现上个月线上问题数量增加了一倍,于是你冲到你的工程师团队工位前怒不可遏地冲他们吼道:我希望这个月的线上问题不超过个位数!你觉得他们能做到吗?
我想说的是,质量不是「希望」的结果,它是付出的收获。关键在于你愿意用什么去交换。
提升质量的诀窍一点也不神秘。口口相传的各类业内实践便是最好的灵丹妙药,比如重构、代码评审、结对编程、流水线集成等等。我们不妨就以单元测试为例,看看我们需要付出多大的成本
首先时间便是一笔可观的支出。以我所在的项目为例,我们为前端React 组件编写单元测试的时间几乎与开发功能的时间相同。注意这还是在没有追求覆盖所有的边界用例,以及没有追求 100%的测试覆盖率的情况下。另外当我们编写的代码导致之前编写的关联测试无法通过流水线时,去查找失败的原因以及修正这些错误也是隐形时间。
其次在我看来最难以逾越的障碍在于对工程文化的重塑。对下要强调保证程序员去写、关注、修复的纪律;对上要争取理解和空间来辅助这些实践,单拎出来任何一件事推动起来都不简单。工程实践天然具有一种反商业活动的特性,它很难被量化、难以一针见效。没有人敢拍着胸脯说在xx 天之内或者当测试覆盖率至少达到 xx 水平之后 bug 数量会降至 xx。我们都不否认它会变得更好。讽刺的是实践带来的「负面」效应是立竿见影的:工程团队的交付速度变慢了。
测试的部分好处还来自未来,比如它能增强我们重构代码和变更架构时的信心,防止旧功能无意被新功能破坏。但我依然无法保证你的收益会何时何地有几倍于付出的到来。
于是现状变成了一方面可见的迭代速度变慢,另一方面成本的付出看不到收益,质量就自然值得被牺牲。
在提升质量的过程中我们解决的不是个体问题而是工业问题,细想这是很难的:一个团队中不同成员的能力不同背景不同,但我们却要设法让它们的产出质量处于某个水平之上。
还债
听上去我们只能义无反顾去相信(take a leap of faith)某些实践能够帮助我们提升质量,且付出的收益是不确定的。但换一个角度想,我们只是在做一些本该做好的事情而已,用户的宽容让质量变得可有可无。
我不否认有时候快比好更重要,只不过当有一天质量变成我们无法再忽视的问题时,别不知所措地想不起来质量是在哪里搞丢的。