转自:http://www.cnblogs.com/supercpp/archive/2011/11/10/2245087.html
如果你与软件行业有若干联系,但是还不知道Joel这个人以及他的博客,那么赶快拿起百度,然后尽可能多的了解他和他的思想,对你肯定有好处。这篇是他博客中的经典之作,收录在他的两本书中:《Joel on Software》和《Smart & Gets Things Done》,这两本书主要收录和整理了他的博客中的经典文章,有必要一看。 要翻译出原作者的味道真的很难,所以我们经常骂一些翻译过来的中文书籍太烂,特别是由那些不懂技术的人翻译的技术书籍。所以如果你是是程序开发人员,再次善意的提醒您:“学好英文”,这句话被很多人重复,也不多我一个了,当然听不听由你。
你有没有听说过SEMA?这是一个非常复杂的软件开发团队评价体系。等等!千万别去研究它!仅仅是理解它就将花掉你六年时间。所以我自己搞了一套软件开发团队评价体系,信不信由你,这套体系最大的优点就是只需三分钟就可掌握!你可以把省下的时间去读医学院了。
Joel 的12条测试问题
- 你们用了源代码管理软件吗?
- 你们是否一步就能实现从源代码到可发布的产品?
- 你们每天都把源代码管理系统的代码做一次生成操作吗?
- 你们有软件Bug管理系统吗?
- 你们在编写新代码前解决bug吗?
- 你们有没有一个时常更新的进度计划?
我的这套体系非常简洁,你只需对每个问题回答“是”或者“否”就可以了,你不需要去算什么每天写的代码行数或者平均bug数等等,回答“是”就给你的团队加一分。但丑话说在前面,可别用我的这套体系去衡量你的核电站管理程序是否安全。
如果你们得了12分,那是最好,得了11分还过得去,但如果只得了10分或低于10分,你们可能就有很严重的问题了。但是事实上大多数的软件开发公司只能得到2到3分,而这些公司往往有很大问题,因为像微软这样的公司一直是保持12分的。
当然,以上法则并不决定成功与否的唯一因素。举一个极端的例子:让一个优秀的开发团队去开发一个没有人需要的软件,那么,开发出来的软件再好也没人会买。同样,一帮程序天才即使一条也不符合以上标准,也能照样搞出一个改变世界的伟大软件。但我告诉你,如果当其他条件都一样的时候,只要做到以上12件事,你的团队就能比那些没做到的更有纪律性并有更好的产出。
1.你们用了源代码管理软件吗?
我用过源代码管理商品软件,也用过免费的,比如CVS,告诉你吧,CVS挺好用(当我写这篇文章之后有了Subversion,它比CVS更好用)。但如果你根本就没有用源代码管理软件,那你就是累死了也没法让你的程序员们协同工作。他们没法知道别人做过些什么,如果出错了也没法恢。源代码管理软件的另外一个好处在于:每个程序员都把源代码签出来存储在自己的机器上,很难发生丢失源代码的事,最起码我还没听说过。
2. 你们是否一步就能实现从源代码到可发布的产品?
我的意思是:从你们最新的源码开始到建立起能够发布的产品需要多少步骤? 一个好的团队应该有一个脚本可自动的实现这个过程:把源文件提取出来,从新编译每一行代码,根据各种编译开关(#ifdef)进行编译,得到各种版本(包括各种语言)的可执行程序,做成安装包,放到最终的发布媒介上,如CD光盘,直接发布到网站上等等。
如果这个过程不是一步做完,就有可能出差错。当你接近产品发布的时侯,你可能很急于想把最后几个bug解决,然后尽快地发布。如果这时候你需要做20步来编译代码,制作安装包...等等,你肯定会急得要命,然后犯一些很不该犯的错误。
正因为这个原因,我工作的前一个公司放弃WISE而改用InstallShield:因为我们需要能够让Widows NT的计划管理程序在夜间自动的启动脚本程序来完成整个自作安装包的过程,WISE不能被Windows NT的计划管理程序启动而InstallShield可以,我们只能放弃使用WISE。(WISE的那帮家伙向我保证他们的下一代产品一定支持在夜里自动运行)
3. 你们每天都把源代码管理系统的代码做一次生成操作吗?
你们在用代码管理系统的时候有没有遇到过这样的事情:一个程序员不小心签入了有问题的源代码导致无法成功生成。比如,他建立了一个新源文件,在他的机器上整个编译得很好,但忘了把它签入到源代码管理系统。他高高兴兴的锁机回家了,可是别人却因为这没法工作下去了,也只好郁闷地回家了。
这种造成没法生成的情况如此糟糕却如此常见,所以如果每天都做一次生成操作的话,就可以尽可能的避免这种事发生。在一个大的团队里,要想保证问题及时得到纠正,最好每天下午(比如午餐时)在服务器上做一次生成操作。午餐前,每个人都尽可能地把改动的源代码都签入,午餐后,大家回来,如果生成成功,好!这时大家再从源代码管理系统里签出最新的源程序接着工作。如果生成失败了,那么找一个人来负责修正它,其他人因为没有签出所以还可以继续在上一个没问题的版本上工作。
在我过去的Excel的开发团队,我们有一条规定:谁造成生成失败,谁就得被罚去负责这个生成过程,直到下一位造成生成失败的人来接任他。这样做不仅可以督促大家少犯这种造成生成失败的错误,而且可以让每个人都有机会去了解生成的过程。
4. 你们有bug管理系统吗?
不论你有任何借口,只要你写程序,哪怕只是一个人的小组,如果你没有一个系统化的管理软件bug的工具,你写的程序的质量一定高不了。许多程序员觉得自己可以用大脑记住发现的bug清单。没门!我最多也就能记住2到3个软bug,而且第二天早上就忘了,或者如果急着发布程序就更容易忘记。你绝对需要一个工具来管这些Bug。软件Bug管理系统有的功能很强大有的也很简单,但至少要包含以下几种信息:
- 记录完整的Bug出现路径
- 正常情况(无Bug)应是怎样
- 现在情况(有Bug)又是怎样
- 谁来负责杀Bug
- 问题有没有解决
如果你觉得用软件虫管理系统太麻烦,可以简化一下,建立一个有以上5列的表来用就行了。
5.在编写新代码前解决bug吗?(即零缺陷,在写新代码前优先搞定所有的已知bug,让新代码在零缺陷的前提下开发)
Microsoft Word的早期版本的开发过程被认为是'死亡之旅'。这个项目似乎永无止尽,这一过程中慢慢丧失了生机。整个项目开发团队每天都日以继夜的工作,但是这个项目却总是延期,而且是一次又一次的延期,每一位团队成员需要面对难以承受的压力。一年以后,当整个项目交付后,Microsoft奖励整个团队到Cancun休假。休假中,Word开发团队坐下来非常严肃的在灵魂的深处回顾了自己和团队的得失。
团队认识到,开发的过程中,团队的管理者始终坚持严格按照计划进行工作。因为解决bug并不是正式的计划中的一部分,所以每一位程序员都急着忙于编写代码,而没有人注意代码的质量,得到的自然是错误百出的代码。同时团队中也没有人试图去修改bug, bug越来越多。这个过程就好比一个程序员需要写出一行代码,来计算Word中一行字的高度(字号大小),但是他很简单的完成了这句代码——return 12。但是并非每行字的高度都是12,而大量后来的代码都调用了他的这一行代码,可想而知有多少功能将由于这行代码而成为bug,如果没有及时修改,进度表就等同一个bug累计表(进度每向前一天就会有新的特性具有bug。此后,这种编写代码的方式被称为'无限缺陷法'。
为了解决这一问题,让项目回到正轨之上,微软采用了我们称之为'零缺陷'的方法。听了这一措施,很多程序员都嗤之以鼻,因为他们觉得这是微软的管理层想通过一个管理制度来消灭bug(实际上这是做不到的。)。而实际上,'零缺陷'的真正含义是指,在开发的过程中,在你决定进行新的代码编写前,你都必须仔细评估已有的bug。理解了‘零缺陷’的真正含义没有哪一个程序员再会表示丝毫的不屑了。
一般来说,bug在你的代码中停留的时间越长,修复这个bug的成本(时间或金钱)就越高。(下面就由短到长的给出不同的情景)
例如,如果只是出现了编译器能够发现的拼写或者语法错误,解决他简直是小菜一碟。
如果你第一次编译和运行你新写的程序的时候就发现了新写的代码中有bug,你就会很容易的修正它(不需要花多少时间),因为所有的代码还清晰的停留在你的脑海中。
当你发现bug可能存在于你一两周之前写的代码中,你就需要一些时间去看懂原来写的代码,但是当你读这些两周前的代码的时候,你还能记起当初你是如何编写这些代码的,所以能在一个合理的时间内解决这个Bug。
可是,当你试图在一两个月之前写的一些代码中去追踪一个bug的时候,你往往已经差不多忘记了大部分你当初写代码的逻辑。所以想要找到并消灭这个bug就会困难的多。更进一步,如果你要去解决其他人代码中的bug,而这个人此刻可能正在'Aruba'逍遥自在的享受着他的假期,你会发现这个过程简直就是在搞科研:你必须慢慢的、有条理的、仔细再仔细的去寻,你肯定无法准确告知找到并修复这个bug需要多少时间。
更为甚者,如果你在已经发布的产品中发现了一个bug,那成本就大了去了。
这就是为什么需要及早消灭bug的原因,因为这样用时最少。这样做的另外一个原因就是,估算编写新代码的时间远比估算消灭一个bug的时间要容易的多。比如,我想让你告诉我编写一个排序的代码需要多长时间,你肯定能给我一个比较精确的时间。但是当我让你告诉我需要多久才能消灭这个bug时,你往往不能给我准确的答案。因为你还不能确定是哪里的错误导致了这个bug,你有可能需要整整三天的时间才能找到这个bug,当然,你也可以碰到2分钟就找到这个bug的情况。
试着想一想,当你的计划中有大量的bug需要被消灭的时候,你的计划是不是也就变得不可控制,或者说难以控制?但是如果你消灭了所有已经发现的bug,你所需要做的就只剩下编写新的代码,这个时候你制定或者修正计划就会准确很多。
'零缺陷'开发方法之所以'伟大'的第三个重要的原因就是因为他能让你更加快速和灵活的应对不断变化的竞争环境。有些程序员会告诉你,'零缺陷'就是要让你的产品随时能够发布。假设,你的竞争对手想到了一个'该死的'新功能,并且想以此来吸引并'偷走'本应该属于你的客户。什么是最有力的反击?就是你马上把这个新功能展示给客户看!当然想要展示功能,就需要此时你手里的程序不会不停的出现那些让人'厌烦'的bugs。
6. 你们有没有一个时常更新的进度计划?
我们为什么要做进度计划?如果你写的程序对公司的业务很重要,那么就有理由相信:知道什么时候能完成这个程序对于公司很重要。程序员懒于制定计划这一点已是众所周知的。他们总是对业务人员嚷嚷:“该完成的时候自然就完成了”
遗憾的是,事情远远没有那么简单。软件公司在发布一个软件之前需要提前做太多的事,这些事必须计划好,比如制作演示样例,产品展示会,广告等等。所有这些都依赖于有一个产品开发计划,并时常更新这计划。
制定产品开发进度计划的另一个关键原因在于,它能让你提早明确哪些产品特性是你需要开发的,而把那些最不重要的产品特性放弃,否则你就可能陷入不重要特性的泥潭(也就是,无法控制产品开发的范围,导致进度总是落后)。
7. 你们有没有产品开发文档?
(译注:关于产品开发文档,涵盖的内容很多,Joel针对这个问题有专门的文章进行阐述,包括如何既要敏捷又具备一定的规范性,做到很好的平衡,这个话题的争论很多,在实践中不断改善才是硬道理。---Ailon)
写产品开发文档这个话题就像用牙线清洁牙齿(用牙线清洁牙齿能保证牙齿健康,可谁每天用牙线清洁牙齿):每个人都同意写产品开发文档很好,但是就是没人去做。
我不太肯定这个现象是怎么产生的,但是一个原因是程序员普遍讨厌写文档。结果,当一个团队都是一些专注于解决问题的程序员的时候,他们就变得更喜欢用代码来表达他们的解决方案,而不是文档。他们情愿一开始就忘情的投入写代码中去,而不是先写产品开发文档。
在软件设计阶段,当你发现问题你能很容易的修正,用几行文字就可。但是一旦开始写代码了,修正问题的成本就会变得非常高,原因有两方面:一是情感上的(人们谁愿意丢掉自己辛辛苦苦写的代码呢?),另一方面是时间开销很大,所以这两方面的原因使得人们从内心中是不愿意去修正问题的。软件开发如果没有预先写产品开发文档往往就会充斥糟糕的设计,并且开发进度很难控制。比如当初Netscape开发浏览器的时候,最开始的四个版本乱七八糟以至于后来管理者愚蠢的将所有代码全部丢弃从新开发,结果所有以前犯的错误又从新犯了一次(这次开发的版本叫Mozilla),这一版本的开发简直就是产生了一个失控的怪兽,花了好几年时间才进入到Alpha阶段。(产品开发的beta,Alpha等等阶段)
我个人认为这个问题可以这么解决:让那些不愿意写文档的程序员参加一个强化的写作培训班,另外一个办法是聘请非常聪明的程序经理来专门写程序开发文档。不管采取何种办法,你应该遵守一个原则:“没有软件开发文档别写代码。”
8. 程序员是否有安静的工作环境?
给知识工作者安静的个人空间可以提高工作效率,这一点在很多书上都提到过。那本经典的软件管理书《人件》对这点进行了很大篇幅的论述。
为什么安静的环境如此重要?我们都知道当知识工作者“沉浸”于工作的时候效率最高,也就是当他全身心的集中精力在处理的问题上,完全忘记周围的环境的时候效率最高,我们把这种状态叫做“集中精力的境界”。这时候他们完全忘记了时间的流逝,由于全神贯注往往做出了一些很棒的东西。只有在这种时候才能有最有效的产出。作家、程序、科学家,甚至是篮球运动员都知道这种集中精力的境界意味着什么。
但是问题在于,集中精神不是那么容易。如果你非要定量描述它,那就这么说吧,一般要想进入工作效率最高的状态,你平均需要15分钟的“热身”时间。有些时候,当你已经很疲劳,或者那天已经做了很多创造性的工作的时候,你就很难再集中精神了,在那天剩下的时间里只能做些无足轻重的事了,比如浏览网页,玩玩俄罗斯方块什么的。
更要命的是这种集中精力的状态很容易被打破。噪音、电话、出去午餐、去星巴克喝杯咖啡,或者同事都能打破这种状态。对了,特别是同事很容易将你踢出这种集中精力的境界。当有同事问你一个问题,表面看起来你只花了一分钟时间回答他,但是实际上之后你可能需要半个小时来恢复到之前的全身心投入状态,你的整天的工作效率都可能成问题(这点大鹏可能很有感触,所以大家最好不要轻易打扰他,有事等中午休息时间再找他)。如果你工作的环境是一个嘈杂的大房间(就像很多咖啡厅想营造的环境),市场部的人员就在程序员旁边大声的与客户打电话,程序员工作效率就成问题了,就会时不时的被打断思路,很难进入那种全神贯注的状态。
对于程序员来说,这点尤为困难。程序员的生产效率依赖于能够在很短的时间里面理清很多细节。任何干扰都能阻碍他们想清一些细节。当你被打断然后继续工作,很多细节都忘了(例如你刚刚用的局部变量名,或者忘记实现某个搜索算法下一步该做什么了),你不得不再从头看你写的代码,这样就极大的影响程序员的工作效率。
让我们来算一个简单的代数问题。 假设如果我们干扰程序员哪怕一分钟,就会是他失去15分钟的生产时间(这点已经很理想了,现实恐怕还不止这么多)。现在有两个程序员Jeff和Mutt,他们坐在一个开放的隔间里面,两个人在邻座。有一天,Mutt记不得strcpy这个函数的Unicode版本叫什么名字了,他可以花30秒自己去查书,也可以问Jeff,这只需要15秒。因为Mutt就坐在Jeff边上,所以他就去问Jeff。结果Jeff就被打扰了,仅仅节约了Mutt15秒的时间,却浪费了Jeff15分钟的时间。
现在我们将他们安排到两个独立的办公室,有墙和门隔着。现在当Mutt记不得那个函数的名字的时候,他也可以自己花30秒时间去查书,或者跑去问Jeff,但是这时候就要花45秒钟的时间,而且还得从椅子上站起来(往往很多时候为这种小问题程序员是不愿意挪窝的),所以Mutt就自己去查书了。这样Mutt就花掉了30秒的时间,但是却节省了Jeff15分钟的时间。岂不妙哉!
9. 你们是否用了能买到的最好的工具?
用很低配置的电脑,就连编译代码这种事也很难在一瞬间完成。如果你的编译过程需要花好几秒的时间,赶紧去买一台好点的电脑吧,那样会节省你很多时间。如果编译过程甚至需要15秒的时间,程序员就会等得很厌烦,这样他们会在编译期间去看一些洋葱新闻(美国一家专业捏造假新闻的恶搞新闻媒体做的东西),有时候会被这些恶搞新闻吸引,结果损失了好几小时的工作时间。
用一台显示器来调试图形用户界面的代码,不说不可能也可以说是件很痛苦的事。如果你在写图形用户界面的代码,用两个显示器会容易的多。(译注:这里指的是双显卡技术而不是买两台电脑,双显用来调试GUI代码的确爽的多)
大部分程序员很多时候都要为一些图标或工具条制作位图,大部分程序员都没有一个好的位图编辑工具。用微软的画图板来编辑位图简直就是一个笑话,但是你还别说大部分程序员就是那么干的。
在我的上一个工作,系统管理员不断的给我发那种自动发送的垃圾邮件:说我用了服务器过多磁盘空间,你知道吗?有220M之多呢(译注:Joel的文字很多充满这种戏谑之语)。我气愤的回答说,按照今天磁盘的价格,我用磁盘空间的这些花费比我用你们家厕所卫生纸的钱少多了。你要知道哪怕我每次只用十秒的时间来清理我的文件夹,都会极大的降低我工作的效率。
顶级的开发团队不会折磨他的程序员,哪怕因为使用一些不强大的工具带来的只是很小的不爽,当这些很小的不爽积累起来就会是程序员恼火和不开心。而不开心的程序员是不可能高效率的工作的。
总结起来,程序员是很容易被贿赂的,你只需要给他们一些很酷的,最新的东西。这比你给他们更多的薪水还管用,并且花费比你加工资要少得多。
10. 你们有软件测试人员吗?
如果你不能保证至少两个到三个程序员就配备一个专职测试人员,那么你要不就发布充满bug的产品,要不就要让$100/小时的程序员来做本可以由$30/小时的测试人员来做的事情。节省测试人员的想法从经济学角度来看是完全错误的,但是很多人没认识到这点。
11. 你在面试应聘程序员的时候让他们写代码了吗?
当你招聘魔术师的时候,可能不让他给你露两手绝活吗?答案是显然的。
当你找厨师为你准备婚宴的时候,你可能不品尝一下他做的菜吗?
是的,很多时候,程序员之所以获得一份工作,往往是因为他有一份给人印象深刻的简历,或者面试官和他很谈得来。或者只是被问到了一些琐碎的问题(比如 CreateDialog() 和 DialogBox() 有什么区别?),这些都是些可以从帮助文档里面查到的问题。然而你不应该关心你要招聘的程序员是否能记住成千上万个这种琐碎的问题,你应该关心他们是否能写代码。 有些时候情况更糟糕,比如问那种“AHA”问题,这种问题当你知道答案的时候非常简单,但是如果你不知道答案,不可能回答得上。(译注:类似于脑筋急转弯的问题)
请停止做以上的傻事吧,面试程序员的时后想做什么都由你,但至少要让他们写一些代码。
12. 你有没有做“走廊易用性”测试?
所谓“走廊易用性”测试是指,在走廊上找那些经过的行人,让他们用一下你做的东西。如果你能找到五个人用一下,你就能找到95%的可能影响易用性的问题。
好的用户界面设计没你想想都那么难,但是如果你想让你的客户喜欢并买你的产品,易用性却是非常的关键。
对于用户界面设计来说,如果你能把你的程序展示给几个人来看(事实上5个到6个就足够了),你就能很快发现用户在用你的软件的时候可能遇到的最大的麻烦。 即使你缺乏用户界面设计技巧,只要你能强迫自己做“走廊易用性”测试,你设计的用户界面就会好很多。