Joel谈软件 12步让代码趋于完善【译】

2000年8月9日 星期三

你听说过SEMA(软件工程测试与分析)吗?那是一个相对难懂的系统——用于衡量一个软件开发小组的好赖。停下来,别点击那个链接,弄懂那个系统兴许长达六年之久。我提出一个我自己的、不负责任、草率的方法测试软件团队的质量。这个方法的好处是它只用大约三分钟。如果你总是节省时间,你可以出门右拐。



Joel的测试:

1.代码源控制软件你有用吗?

2.你能一步建立工程吗?

3.平时做工程吗?

4.你有bug数据库吗?

5.在写新代码前bug是否都已排除?

6.你有不断更新的计划表单吗?

7.你有说明书吗?

8.程序员有安静的工作环境吗?

9.你用的是金钱可以买到的最好的工具吗?

10.你有测试员吗?

11.招聘时要求求职者写代码吗?

12.你的代码有做可视性测试吗?



  

  Joel的测试的奇妙之处在于,对于每个问题,你都能很快得出“是”与“不是”。你不必弄明白每行代码和平均bugs变化曲线。每个回答“是”的问题,给团队加一分。Joel的测试初衷是为了测试那些游手好闲的人,如果你用于测试核软件工程,请三思。

得分12分完美,11分可以忍受、一般般,但是10分或者更低团队则有严重问题。事实是, 许多软件开发团队都仅仅只得2、3分,他们需要帮助,因为像微软这样的公司一直都是12分。

当然,这不是决定成功或失败唯一的因素:尤其,如果你有一个优秀的软件工程团队,却设计一个人们不要的产品也是枉然。你可以想象一队“带枪”的人不从事靠谱的项目却还想着改变世界。但是,其他条件不变的前提下,如果你做到以上12点,你将拥有一个训练有素的团队始终如一的产出。



1.代码源控制软件你有用吗?

我用商业源控制代码包,并且已经开始使用CVS,它很好用,而且是免费的。但是如果你没有使用源控制,那么你和其它程序员一起做项目就会犯难。另外,使用源控制还有一个好处是源代码本身在每个程序员的硬盘里——我还从没有听说哪个工程因为使用源码控制而丢失代码。



2.你能一步建立工程吗?

我的意思是:从最近的工程编写可运行程序需要几步?对于良好的团队,运行一个脚本可以完整的检测出抓取、重建每行代码、可执行文件生成、有关的所有版本、语言、定义、创建安装包,生成最终文件——CDROM布局,网页下载,等等。

如果这个过程超过一步,很容易出错。当你接近完工时,你想要尽可能快的修复最后的bug周期以期能够执行。如果编译、运行安装包等执行了20几步,你犯了一个愚蠢的错误,你会感到崩溃。

由于这个原因,最后的软件一定是简单明快的,我们需要它安装尽可能快,从一个脚本开始,自动的使用元调度执行。如果不支持夜间执行,丢掉(先前一个人保证能夜里执行,结果却不能,所以我们扔掉它)。



3.平时做工程吗?

当你使用源控制时,有时候一个程序员突然检查东西破坏了工程。例如,他们增加了了个源文件,在他们的机器上一切运行良好,但是他们忘记把更改写会代码库。而后,关上机器高兴的回家了。但是,其他人不能工作了,他们也回家了,心情沮丧。

破坏工程如此糟糕(却又常见),它有助于构建、有助于缺口补救而不被人注意。在大的团队里,一个好的办法是在每天饭前完成修补漏洞。每个人在饭前尽可能纠错漏洞,当他们回来时,工程还是好的。如果确实如此,太好了,大家可以调出最近的版本继续工作。如果工程执行失败,你修复它,其他人可以调出早先时候完整可运行的版本继续工作。

在Excel团队里,我们有一个规矩,不管谁破坏了工程,作为惩罚他有义务照看工程直到有人破坏它。这个办法刺激队员尽可能不破坏工程非常有效,它使队员轮流纵览工程用以了解工程是怎么运行的。

更多关于工程文章:Daily Builds are Your Friend.



4.你有bug数据库吗?

  我不关在乎你说的。如果你正在做工程,即使是一个人的组,如果没有一个有组织的数据库列出代码中出现的bugs,你码的代码是低效的。许多程序员认为他们可以在大脑中记住bugs。这纯粹胡扯,我同时记住2到3个bugs算是极限了,第二天早晨或者突发事情打断,它们就溜走了。然后你不得不重新跟踪bugs。

bug数据库可复杂可简单。最简单的也必须包含以下:

    这个bug重现的完整步骤;

    1.期望的行为;

    2.观察到的行为;

    3.谁发现的;

    4.是否已经修复;

  如果bug跟踪软件的复杂性是唯一使你不能跟踪bug的理由,那么建立一个有以上五栏的表格就好了,使用它。

  更多过于bug跟踪:Painless Bug Tracking.



  5.在写新代码前bug是否都已排除?

  微软最初Word版本被认为是“向死亡行军”工程。它花费了那么久,一直持续。全队滑稽的工作一个小时又一个小时,工程不断被延误,延误,延误······,压力之大难以想象。当一切到达边缘,年底,微软放全队人员去坎昆度假,然后坐下来认真思考。

  他们意识到项目经理一直再赶时间表,程序员匆匆完成编码,写了一大堆糟糕的代码,修复bugs从来没在计划之内。没有试图减少bug数目,却恰恰相反。故事是这样的,一个程序员写了有关计算文本高度的代码,简单写了“return 12;”等着机器报错函数部分代码有问题。时间计划表仅仅是目录表慢慢变为bugs。尸检行业,称之为无限缺陷法。

  为了纠正错误,团队成员每个人采用“零缺陷法”。公司其他程序员都笑了,听起来好像管理者发号施令的次数可以减少bug数一样。事实上,“零缺陷法”意味着在任何时间,修复bug的优先级是最高的,即是要写新代码。

  一般而言,修复bug拖得时间越久,修复的代价(时间和金钱)也越高。

  例如,你犯了排版或者语法错误,编译器捕获它并且修复它基本上小菜一碟。

  你第一次看到有错误在你的代码中,当你运行它时。此时,你可以毫不费力马上修复它,因为它们还是你的脑中浮现。

  如果你在你几天前写的代码中发现了错误,修复它可得花费一会儿时间,但是从新读你写过的代码,你能回忆起所有事情,完全可以在一个合理的时间修复它。

  但是如果你在你几个月前写的代码中发现错,关于代码的许多事情你可能都不记得了,修复它谈何容易。何况,如果你修复别人的代码,此人正巧在加勒比海度假,这种情况下,修复bug像是一门科学:不得不放慢脚步,系统地、认真地处理,而且你也不能保证多久能发现线索。

  并且如果你发现代码中的bug已经用于实践,你修复它将会付出难以想象的代价。

  这是立刻修复代码的一个原因:因为它花费的时间很短。

  另外一个原因是,这关系到很容易预测多久可以写新代码相比修复现有bug。例如,如果我问你写一个表单分类代码需要多久,你可以给出相当准确的预期。但是,如果我问你运行的IE5.5修复需要多久,无法回答,因为你不知道是什么引起bug。它可能需要三天亦或是两分钟。

  也就是说如果你有一个需要修复的bug表单,修复时间是不确定的。但是如果你现已修复了已知的所有bug,仅剩新代码,这时候你的时间会惊人的准确。

  另外保持bug归零的好处是你可以比你的竞争对手更快的应对。一些程序员认为这是保持产品一只叫座的原因。当然,如果你的竞争对手引入新功能偷走了你的客户,你也可以迅速把该功能植入你的产品,无需修复大量bug。



  6.你有更新的计划表单吗?

  是什么驱使我们有做计划的必要。如果你的代码对公司很重要,有太多的理由解释为什么代码完成时间对于公司的重要性。程序员是公认的厌恶制定计划。“它该完成时自会完成!”他们对公司的人大喊大叫。

  不幸的是,这种趋势并没有削减。公司有太多的计划内决定需要代码:样本、交易展示和广告等。做这些的唯一方法是有一个计划表,并保持更新。

  有一个计划表的另外重要之处是迫使你,决定什么你将会去做,做最重要的而不是砍掉它们做些无用功(有名范围渐变)。

  保持计划不需要努力。读Painless Bug Tracking,它讲述了怎么用最简单的方法做出完美的计划。



  7.你有说明书吗?

  说明文档就好像一个流程:都承认那是个好主意但没有人那么干。

  我不知道这是为什么,兴许是大多数程序员都痛恨写说明文档。导致的结果是,当团队要搞定一个问题时,程序员更愿意用代码问题而不是说明文档。他们更愿意潜水写代码而不是文档。

  在设计阶段,发现了问题可以很容易通过文本文档补救。一旦代码实现,发现问题不久的代价往往很高,由于时间因素的影响(厌恶丢掉代码),促成修复问题的障碍。软件开发没有软件前期设计往往造成设计糟糕和进度失控。在浏览器开发就有这样的问题,当前四各版本步入混乱,管理人愚蠢的决定丢掉代码从头开始。而后,相同的问题再次出现,开发了一个混乱、失控的怪物,多年以后又回到了开始阶段。

  我的宠物理论是通过让程序员接受集中写作训练课程而愿意书写,从而解决问题。或者是雇佣写设计文档的明智软件管理者。不管什么情况,你应该强制一条原则“没有文档,代码也没有必要”。

  了解更多如何说明文档书写,读4-part series



  8.程序员有安静的工作环境吗?

  有大量文献记载高效的出产是给那些富于学识员工提供安静和隐私的办公空间。著名的软件管理书籍——《人件》论述,这样的生产效率受益广泛。

  这是麻烦的。我们都知道知识工作者的工作方式是“流”,或者是“空间”,这样他们能够专心投入工作和获得足够的环境调整。他们与世隔绝创造出伟大的东西。这使得他们卓有成效的完成所有工作。作家、程序员和科学家,甚至是篮球运动员都会告诉你,保持专注。

  问题是,保持专注并不那么容易。当你试图去测算它时,进入状态(生产效率最大)平均要花费15分钟。有时,如果你累了或者完成了一些创造性工作,你就很难继续投入工作了,把剩余的时间用来瞎逛、冲浪和俄罗斯方块。

  另一个问题是,专注很容易被打断。噪音、电话、吃饭时间、咖啡时间和同事的打扰,尤其是同事被同事打断——所有这一切。如果同事问一个问题打断你一分钟,这样打断已经足够糟糕,你不得不花费半小时再次进入专注状态,整体效率下降。如果你是在一个充斥着咖啡因的大房间里办公,市场部的伙计正在电话里呵斥旁边的程序员,你被一次次打断永远不会进入状态,效率甚低。

  对于程序员,环境更是重要。工作效率取决于能够短期在大脑中兼顾许多细节。任何的打断都可能使细节烟消云散。当你恢复工作,记不起任何细节(用过的变量名、搜索算法的实现),还不得不回忆,这使一切变得很慢,直到恢复到原来速度。

  这是一个简单的算数。(有证据表明)打断一个程序员一分钟,流失掉十五分钟的效率。基于这个,假设有两个程序员A和B在一个房间办公,B因为一个字符问题卡住需要解决,自己查阅资料需要30秒,问别人需要15秒。恰巧A在旁边,B问A花费15秒就解决了问题。却流失了A的15分钟的效率,而B仅仅节省了15秒。

  现在我们让A和B分开办公,单独房间。B还是因为字符问题,自己解决时间仍是30秒,当然也可以跑去问A,需要45秒——涉及到站起来跑路(这对于程序员平均身体情况可不是个容易的事儿)。于是B自己解决了,花费时间30秒,这样他就为A节省了15分钟啊!



  9.你用的是金钱可以买到的最好开发工具吗?

  用汇编语言写的代码还是不能在众多PC立即执行。如果你的应用编译超过几秒钟甚至更多,最新的、强大的机器将节省你的时间。如果用时15秒,程序员会感到厌倦而切换到洋葱网(the onion 美国一个幽默新闻网站),这将会吸引他们从而稀释掉数小时生产力。

  一个监控界面调试GUI程序痛苦不堪,如果你有两个,事情将容易很多。

  许多程序员最后不得不通过位图调试图标和工具条,他们位图编辑能力并不好。试着用微软的paint调试简直是玩笑,而这些工作由不得不做。

  我的上一份工作,系统管理员自动发送垃圾邮件达到我的服务器硬盘220兆左右。这些硬盘空间成本明显低于厕所厕纸成本。即使是话费10分钟的时间清理这些目录都是生产力的极大浪费。

  顶级的团队不会折磨他们的程序员。甚至是小问题引起的开发工具动力不足加起来,足以使程序员抓狂和不开心。烦躁的程序员不是多产的程序员。

  综上,程序员是最容易收买的,酷的、时新的工具。这实际要比支付给他们更有竞争的薪水划算。



  10.你有测试员吗?

  如果你的团队没有专门的测试员,至少两到三个人用一个,代码出现bug,100美元每小时的程序员和30美元每小时的测试员哪个更滑算。这么简单的道理被许多人忽视了。

  了解更多读:Top Five (Wrong) Reasons You Don‘t Have Testers



  11.招聘时要求求职者写代码吗?

  你会要一个没有给你表演过魔术的魔术师吗?当然不会。

  你会让一个你没有品尝过他们食物的筹备者准备婚礼吗?我怀疑(除非她是玛姬姑妈,你不让她做蛋糕她会恨你一辈子)。

  诚然,每天,都有程序员因为出众的简历和面试官喜欢和他们聊天而被雇佣。或者面试官会问一些琐碎的问题(两个函数区别),这些都可以从文档中查到。你不关心他们记得程序中成千的无关琐事,你在乎他们能否写出程序。或者,当面试官问类似“啊哈”问题时,这类问题看似很简单,如果你不知道就另当别论了。

  请停止这样做!面试中不管你想让招聘者做什么,一定让他写点儿代码。

更多关于招聘建议,移步Guerrilla Guide to Interviewing.



  12.你的代码有做可视性性检测吗?

  走廊可用性测试实验,你随便在走廊找个人,强迫他用你写的代码。如果你让五个人用你刚刚写的代码,你就会知道代码中95%的可用性问题。

  好的用户界面没你想的那么难,而且它很重要,如果你想让用户喜爱并购买你的产品。你可以读我的free online book on UI design,简易读本。

  但是用户界面最重要的是如果你把你的东西向少数人展示(5到6个足以),就会发现最大的问题。Jakob Nielsen‘s article的文章告诉你为什么。即使你的UI设计技巧欠缺,只要你强迫自己做走廊可用性测试,它不花钱,你的UI将会越来越好。



注:以上均为本人翻译,原文出字Joel on Software。多处翻译欠妥,欢迎指正!

时间: 2024-08-03 10:39:54

Joel谈软件 12步让代码趋于完善【译】的相关文章

浅谈软件工程师的代码素养

WeTest 导读 写这篇文章时内心是比较忐忑的,因为文章的话题范围非常大,怕自己驾驭不了.在实际工作中,维护过很多类型的代码,其中不乏高级工程师完成的逻辑,大家的需求能力都很不错,能够快速满足产品的需要,但很少能有人能注意到代码的整洁度,甚至很多代码经过多人维护后已经变得无法再进行任何一处的修改,最后不得不花大量的时间进行重构.因此我决定还是写一篇文章来"浅谈"软件工程师应具备的代码素养,希望能够对大家有所帮助,水平所限,如有不当之处还请不吝指正~ "程序是写给人读的,只是

12步轻松搞定python装饰器

12步轻松搞定python装饰器 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需要你了解一些函数式编程的概念,当然还有理解在python中定义和调用函数相关语法的一些特点. 我没法让装饰器变得简单,但是通过一步步的剖析,我也许能够让你在理解装饰器的时候更自信一点.因为装饰器很复杂,这篇文章将会很长(自己都说很长,还敢这么多废话blablabla...前戏就不继续翻译直接省略了) 1. 函数 在python中,函数通

让你提前认识软件开发(45):代码的第一印象

第3部分 软件研发工作总结 代码的第一印象 我们都很注重给别人的第一印象,也有很多书籍教我们怎样给别人留下一个美好印象的.确实,如果我们第一眼看到某个人,就觉得很不爽,那么一定会在心理上产生抵触,以后再见到他,会有一种疏远的感觉.也正因为如此,当今社会交往中的"面子工程"很重要,不管怎样,先撑足了自己的脸面再说. 代码也一样,也会给别人留下或好或差的印象.当我们看到优美的代码时,会有一种想继续研究下去的欲望,甚至会有一种觉得很享受的感觉.相反,当我们看到丑陋的代码时,就会咬牙切齿,因为

浅谈软件项目的需求管理

软件项目区别于其它项目的最显著的特征是其不可见性,它不像硬件购销.建筑工程,都是实实在在可见的东西.而软件项目在系统交付之前很长一段时间,客户是无法感知自己想要的系统究竟是什么样子.因此,需求管理就显得十分重要,据相关统计数据分析,软件项目90%以上失败的原因都在于没有重视需求或者需求管理方面做的不到位导致的. 需求管理作为软件项目管理的一个重要内容,贯穿项目实施的全生命周期.俗话说:万事开头难.需求作为软件开发的第一个环节,其重要性不言而喻.市面上关于需求管理的相关理论和书籍很多,但多数停留在

浅谈Android保护技术__代码混淆

浅谈Android保护技术__代码混淆 代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为.将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字.比如改写成单个字母,或是简短的无意义字母组合,甚至改写成"__"这样的符号,使得阅读的人无法根据名字猜测其用途.对于支持反射的语言,代码混淆有可能与反射发生冲突.代码混淆并不能真正阻止反向工程,只能增大其难度.因此,对于对安全性要求很高的场合,仅仅

再谈软件测试方法之系统测试

此文再谈"软件测试方法之系统测试",是源于本人上篇博文"软件测试方法之系统测试"的总结存在的一些问题做一下自我批注和更正. 首先看一下我的上篇博文主要讲了哪些内容,也可见其目录: 第一部分:系统测试的基本概念(系统测试的定义.目的.方法): 第二部分:系统测试的两个主要方法--功能测试和性能测试. 这样分析看来我的那篇长篇大论其实并没有多少内容.根据我的指导老师(米老师)的学习理论,总结应该是提纲挈领,因为我们的大脑对于越少的内容记忆的越清楚,越多反而记不清楚. 这

浅谈软件性能测试中关键指标的监控与分析

浅谈软件性能测试中关键指标的监控与分析 一.软件性能测试需要监控哪些关键指标? 软件性能测试的目的主要有以下三点: Ø  评价系统当前性能,判断系统是否满足预期的性能需求. Ø  寻找软件系统可能存在的性能问题,定位性能瓶颈并解决问题. Ø  判定软件系统的性能表现,预见系统负载压力承受力,在应用部署之前,评估系统性能. 而对于用户来说,则最关注的是当前系统: Ø  是否满足上线性能要求? Ø  系统极限承载如何? Ø  系统稳定性如何? 因此,针对以上性能测试的目的以及用户的关注点,要达到以上

软件开发中部分代码的注解

初次接触软件开发,先是阅读别人的代码.学习别人的一些经验!下面是遇到的一些代码及注解! @ParentPackage("basePackage")    // 默认继承struts.xml文件的<package name="basePackage" extends="struts-default"> /* * 函数功能:将对象转换成Json字符串,并响应回前台. * 转换的原因:页面使用的数据格式为JSON * 一般我们在服务端中使用

(12)自定义异常代码练习

public class computer { private int i = 1; public void run() throws LanPingExpion, MaoYanExcetion { if (i ==2 ) throw new LanPingExpion("蓝屏了"); if (i ==3) { throw new MaoYanExcetion("冒烟了"); } System.out.println("电脑运行"); } pub