急功近利的开发人员VS止步不前的开发人员

摘要

在为了闲适安逸(相对而言)和金钱财富离开硬件领域,进入软件行业之前,我最早的一份工程师工作是关于芯片设计的。我还记得,当我了解到有多少有问题的处理器被用于测试电路时,我有多震惊。“为什么要浪费这么多处理器在测试上,”当时我想,“为什么我们不能最开始就把它弄对了?”哦,当时我可真是好傻好天真。

1459999044-3341-20160406204743875-292042143

英文原文:These are testing times: mavericks vs. icepeople

在为了闲适安逸(相对而言)和金钱财富离开硬件领域,进入软件行业之前,我最早的一份工程师工作是关于芯片设计的。我还记得,当我了解到有多少有问题的处理器被用于测试电路时,我有多震惊。“为什么要浪费这么多处理器在测试上,”当时我想,“为什么我们不能最开始就把它弄对了?”哦,当时我可真是好傻好天真。

工程师的实际工作很快就会教会一个人:除了氢元素以外,这个世界最不缺的就是对于人们最初设想的嘲弄。甚至在种种变幻莫测的现实状况都已经被“理想状况下”几个字排除的软件行业,这也是一道铁律。墨菲定律实际上是一种很乐观主义的说法:事实上,并不是任何事情都有可能出错——你通常会碰到一些此前你没想到和你的问题有关的因素,而这些因素往往会引发一连串让你追悔莫及的灾难。

那么,我们该怎么做呢?我们可以深入全面地采取一系列防卫措施。我们遵循 “稳健性原则”(robustness principle,又称“鲁棒性原则”、“健壮性原则”)。我们“总是假设那些让你无法继续维护代码的人是知道你住在哪儿的暴力精神病患者,并以此为先决条件进行编码 ”。我们采取敏捷开发方式(是真的敏捷开发,而不是那种知其然而不知其所以然的敏捷开发)。最重要的是,我们编写测试。对吧?没错吧?

……唔,没错,就是这样。在软件工程公司 HappyFunCorp 工作的时候,我每天都会进行大量的面试,几乎我面试的每一个初级开发人员都会向我保证,他们非常热衷于测试。但是同样,在软件工程公司 HappyFunCorp 工作的时候,我也常常被叫去帮忙解救那些带着现有代码库来找我们的客户——你知道我在这些案例中很少看到什么吗?没错,就是有用的、更新过的测试。

我没必要责备他们。或许在你看来, 现在的网页开发很糟糕 ,就像 现在大多数工具 / 服务器开发 一样;现在的应用程序开发(尤其是安卓应用的开发)也简直可以说是一团乱……老板 / 顾客总是在催促开发者更快地开发、更新软件,而要是我们得省略某些环节以便更快地完成开发,我们通常第一个选择舍弃的就是测试环节。

当然,每个人都可以指责说,这种方式或许从短期来看可以帮助你节省一个礼拜的时间,但是要不了多久,接踵而来的麻烦就会浪费你好几个月的时间。没错,事实确实如此。但是,有一个原因让许多开发者产生了对测试敬而远之的心态:糟糕的测试环节造成的影响几乎和没有测试环节一样恶劣,有时甚至比没有测试环节更加恶劣。甚至在初级开发人员确实打算编写测试的时候,他们也会把测试编写环节当成看牙医——他们会把编写测试当成某种痛苦不堪的任务,尽可能快地去解决它。因此,他们会利用某种似乎能够用于任何他们正在使用的结构框架的测试工具,编写——或者自动生成——一些单元测试,结束测试编写,继续下一环节。

啊哈,单元测试。

2 个单元测试,0 个综合测试 pic.twitter.com/V2Z9F4G1sJ

——Practical Developer(@ThePracticalDev),2016 年 1 月 14 日 。

单元测试会把你的整个项目弄得乱七八糟,增加项目的认知负荷,创造代码变化时需要改变的相关数据……当然,它也能找到一些编写得非常好的端对端综合测试找不出的程序错误,但是,这种情况出现得太少了。当然了,如果你在编写一个自动驾驶仪的程序,你肯定希望程序的代码覆盖率能达到 100%。但是,我们绝不应该假装这些测试没有隐含成本(包括短期的和长期的)。就像许多工程工作一样,这是一种权衡、一种对最有效点的搜寻。而对大多数项目来说,最好的测试方式显然并非最全面的测试。

而“端对端”测试的定义通常很灵活。众所周知,自动化用户界面测试是非常困难的。根据我的经验,自动化用户界面测试的存在可能非常令人印象深刻,但是它的实际作用却很有限,就像会做算数的狗狗一样。因此,我们很难将一个端对端测试用于某个一开始就不是其测试对象的网站、服务或者应用程序。(不过,至少负载测试这些年来已经变得简单易用多了,比如 loader.io 就特别棒)。

我面试时碰到的高级开发者往往会表现出一种谨慎的态度——因为他们知道他们要说的话听上去像是异端邪说——他们会说:“唔,测试是很重要,但是你在考虑测试的时候得务实一点。”是的,事实确实如此。

现如今,从事开发工作就像是在享用餐品火候不足的自助餐——今天你想使用哪种有缺陷的半成熟框架?但说到底,许多开发人员之所以不编写测试,或者编写一些不走心的单元测试,原因在于心态而非素材。

目前,有许多开发团队把自己称之为“敏捷开发”团队。但真正的敏捷开发团队很少。(居然有那么多人认为只要每天都开会他们就是一个敏捷开发团队了,天哪,我简直要哭了。)正如 Sauce Labs 发布的这份 测试现状报告(PDF 版)所言,作为一个行业,我们还有很长的路要走。(我不同意这份报告对于敏捷开发的定义——我不同意对敏捷开发下任何固定的定义——不过,这份报告指出的整体趋势在我看来是正确的。)

迷途的开发者们省略了某些环节,只一心想着尽快开发出成品;他们没能设计测试、没能编写测试,他们把这些隐藏在冰面下的问题抛给了下一位可怜的开发者。批评谴责这些开发人员很容易,而且也没批评错。但是,我们也应该看到,这些开发人员尽快开发出成品、尽快有所突破的迫切渴望有其值得赞扬的一面——虽说在某些极端情况下,这可能会致使开发人员大量使用开源脚本语言。(开玩笑的啦。)

另外,还有一些 固步自封的开发者 看重深思熟虑、细致分析和测试驱动开发,说起各色理论来头头是道。可是,粗制滥造出没有意义的单元测试的往往也是这群人——因为这样一来,他们就可以宣称他们的代码覆盖率高达 90% 了。他们会为了获得“认证的敏捷项目管理专家”(Certified Scrum Masters)的称号而抛弃真正的敏捷开发习惯。他们害怕冒险,害怕进入未知的领域。批评谴责这些人倒也没有批评错。

一个理想的世界应该既有一心只想着尽快开发出新产品的开发人员,也有固步自封的开发人员,他们会彼此推动,共同进步。我曾在好几个这样运作的团队里工作过,他们都非常优秀。但如今更常见的情况是,这两类开发人员只是互相说些空话。我本来是觉得,作为一个行业,我们现如今的发展状况应该更好才对。

翻译:钱功毅(@钱南瓜)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: