改进代码的 12 个步骤
|
如果你把这 12 件事做好了,你将拥有一支纪律严明的团队,能够始终如一地交付。
1. 你使用源代码管理吗?
我使用过商业源代码管理包,也使用过免费的 CVS,让我告诉你,CVS 很好。但是,如果你没有源代码管理,你就会在试图让程序员一起工作时感到压力。程序员无法知道其他人做了什么。错误不能轻易回滚。源代码管理系统的另一个巧妙之处在于,源代码本身在每个程序员的硬盘上都签出——我从未听说过使用源代码管理的项目会丢失大量代码。
2. 你能一步到位地完成构建吗?
我的意思是:从最新的源快照进行交付构建需要多少步骤?在优秀的团队中,你可以运行一个脚本,从头开始进行完整的检出,重新构建每一行代码,制作各种版本、语言和 #ifdef 组合的 EXE,创建安装包,并创建最终媒体——CDROM 布局、下载网站等等。
如果该过程需要多个步骤,则容易出错。当你接近发货时,你希望有一个非常快的周期来修复“最后一个”错误,制作最终的EXE等。如果编译代码、运行安装构建器等需要 20 个步骤,你会发疯,你会犯愚蠢的错误。
正是出于这个原因,我工作的最后一家公司从 WISE 切换到 InstallShield:我们要求安装过程能够使用 NT 调度程序从脚本自动运行,而 WISE 不能在一夜之间从调度程序运行,所以我们把它扔掉了。(WISE的好心人向我保证,他们的最新版本确实支持夜间构建。
3. 你每天都会做构建吗?
使用源代码管理时,有时一个程序员会意外签入破坏生成的内容。例如,他们添加了一个新的源文件,并且在他们的机器上一切都编译良好,但他们忘记将源文件添加到代码存储库中。于是他们锁上机器,回家了,忘乎所以,高兴不已。但是没有其他人可以工作,所以他们也不得不回家,不开心。
破坏构建是如此糟糕(而且如此普遍),以至于它有助于进行日常构建,以确保不会忽视任何损坏。在大型团队中,确保立即修复破损的一个好方法是每天下午在午餐时间进行每日构建。每个人都在午餐前尽可能多地签到。当他们回来时,构建就完成了。如果它有效,那就太好了!每个人都检查了最新版本的源代码并继续工作。如果构建失败,您可以修复它,但每个人都可以继续使用预构建的、完整的源代码版本。
在 Excel 团队中,我们有一个规则,即作为他们的“惩罚”,无论谁破坏了构建,都有责任照看构建,直到其他人破坏它。这是一个很好的激励措施,可以不破坏构建,也是一种在构建过程中轮换每个人的好方法,这样每个人都可以了解它是如何工作的。
在我的文章《每日构建是你的朋友》中阅读有关每日构建的更多信息。
4. 你有错误数据库吗?
我不在乎你说什么。如果你正在开发代码,即使是在一个团队中,如果没有一个有组织的数据库列出代码中所有已知的错误,你就会发布低质量的代码。许多程序员认为他们可以把错误列表记在脑子里。废话。我一次记不住超过两三个虫子,第二天早上,或者在匆忙的运输中,它们被遗忘了。您绝对必须正式跟踪错误。
Bug 数据库可以很复杂,也可以很简单。对于每个 bug,最小、有用的 bug 数据库必须包含以下数据:
- 完成重现错误的步骤
- 预期行为
- 观察到的(错误)行为
- 分配给谁
- 是否已修复
如果错误跟踪软件的复杂性是唯一阻止您跟踪错误的原因,只需使用这些关键字段制作一个简单的 5 列表并开始使用它。
5. 在编写新代码之前,你会修复错误吗?
Microsoft Word for Windows的第一个版本被认为是一个“死亡行军”项目。它花了很长时间。它一直在滑落。整个团队都在荒谬地工作,项目一次又一次地被推迟,压力令人难以置信。当这个的东西终于发货时,晚了好几年,Microsoft把整个团队送到坎昆度假,然后坐下来进行一些认真的反省。
他们意识到,项目经理一直坚持遵守“时间表”,以至于程序员只是匆匆忙忙地完成编码过程,编写了极其糟糕的代码,因为错误修复阶段不是正式时间表的一部分。没有试图减少错误倒计时。恰恰相反。故事是这样的,一个程序员,他必须编写代码来计算一行文本的高度,他只是写了“return 12”,然后等待错误报告进来,说明他的函数并不总是正确的。时间表只是一个等待变成错误的功能清单。在事后分析中,这被称为“无限缺陷方法”。
为了纠正这个问题,Microsoft普遍采用了一种叫做“零缺陷方法”的方法。公司里的许多程序员都咯咯地笑了起来,因为这听起来像是管理层认为他们可以通过执行命令来减少错误数量。实际上,“零缺陷”意味着在任何给定时间,最高优先级是在编写任何新代码之前消除错误。原因如下。
一般来说,在修复错误之前等待的时间越长,修复成本(时间和金钱)就越高。
例如,当您犯了编译器捕获的拼写错误或语法错误时,修复它基本上是微不足道的。
当你的代码中有一个错误,当你第一次尝试运行它时看到它,你将能够立即修复它,因为所有的代码在你的脑海中仍然记忆犹新。
如果你在几天前编写的某个代码中发现了一个错误,你需要一段时间来寻找它,但是当你重新阅读你写的代码时,你会记住所有内容,并且你将能够在合理的时间内修复这个错误。
但是,如果你在几个月前编写的代码中发现了一个错误,你可能已经忘记了关于该代码的很多事情,而且修复起来要困难得多。到那时,你可能正在修复别人的代码,而他们可能正在阿鲁巴岛度假,在这种情况下,修复错误就像科学一样:你必须缓慢、有条不紊、一丝不苟,而且你不能确定需要多长时间才能找到治疗方法。
如果你在已经发布的代码中发现了一个错误,你将产生难以置信的费用来修复它。
这是立即修复错误的原因之一:因为它花费的时间更少。还有另一个原因,它与以下事实有关:预测编写新代码所需的时间比修复现有错误更容易。例如,如果我让你预测编写代码对列表进行排序需要多长时间,你可以给我一个很好的估计。但是,如果我问你如何预测在安装了 Internet Explorer 5.5 的情况下,修复代码不起作用的错误需要多长时间,你甚至无法猜测,因为你不知道(根据定义)是什么导致了这个错误。可能需要 3 天才能找到它,或者可能需要 2 分钟。
这意味着,如果你的日程安排中还有很多错误需要修复,那么这个日程安排是不可靠的。但是,如果您已经修复了所有已知的错误,并且只剩下新代码,那么您的日程安排将更加准确。
将错误计数保持在零的另一个好处是,您可以更快地响应竞争。一些程序员认为这是让产品随时准备好发货。然后,如果您的竞争对手推出了一项杀手级新功能,正在窃取您的客户,您可以仅实现该功能并立即发布,而无需修复大量累积的错误。
6. 你有最新的时间表吗?
这就把我们带到了日程安排上。如果你的代码对业务很重要,那么有很多原因可以解释为什么知道代码何时完成对业务很重要。程序员在制定时间表方面是出了名的蹩脚。“当它完成时,它就会完成!”他们对商人大喊大叫。
不幸的是,这并不能解决问题。在发布代码之前,企业需要做出太多的规划决策:演示、贸易展览、广告等。而做到这一点的唯一方法是制定一个时间表,并使其保持最新状态。
制定时间表的另一个关键因素是,它迫使你决定要做什么功能,然后它迫使你选择最不重要的功能并削减它们,而不是陷入特征性(又名范围蔓延)。
7.你有规格吗?
编写规范就像使用牙线一样:每个人都同意这是一件好事,但没有人这样做。
我不确定为什么会这样,但这可能是因为大多数程序员讨厌编写文档。因此,当仅由程序员组成的团队处理问题时,他们更喜欢用代码而不是文档来表达他们的解决方案。他们宁愿潜心编写代码,也不愿先生成规范。
在设计阶段,当您发现问题时,您可以通过编辑几行文本轻松修复它们。一旦代码被编写出来,修复问题的成本就会大大增加,无论是在情感上(人们讨厌扔掉代码)还是在时间上,所以实际解决问题是有阻力的。不是根据规范构建的软件通常最终会设计得很糟糕,并且进度会失控。这似乎是 Netscape 的问题所在,前四个版本变得如此混乱,以至于管理层愚蠢地决定扔掉代码并重新开始。然后他们在Mozilla上再次犯了这个错误,创造了一个失控的怪物,花了几年时间才达到alpha阶段。
我的理论是,这个问题可以通过教程序员不那么不情愿地成为作家来解决,方法是让他们去参加写作的强化课程。另一种解决方案是聘请聪明的项目经理来制作书面规范。无论哪种情况,您都应该强制执行简单的规则“没有规范就没有代码”。
通过阅读我的 4 部分系列,了解有关编写规范的所有信息。
8. 程序员有安静的工作条件吗?
通过为知识工作者提供空间、安静和隐私,可以提高生产力。经典的软件管理书籍《Peopleware》广泛地记录了这些生产力优势。
麻烦来了。我们都知道,知识工作者通过进入“心流”(也称为“在区域”)中才能发挥最佳效果,在那里他们完全专注于自己的工作并完全脱离环境。他们忘记了时间,通过绝对的专注创造了伟大的东西。这是他们完成所有生产性工作的时候。作家、程序员、科学家,甚至篮球运动员都会告诉你关于在这个区域的信息。
麻烦的是,进入“区域”并不容易。当您尝试测量它时,看起来平均需要 15 分钟才能开始以最大生产力工作。有时,如果你累了,或者那天已经做了很多创造性的工作,你就无法进入这个区域,你把剩下的工作时间都花在摆弄、阅读网络、玩俄罗斯方块上。
另一个麻烦是很容易被淘汰出该区域。噪音、电话、外出吃午饭、不得不开车 5 分钟去星巴克喝咖啡,以及同事的打扰——尤其是同事的打扰——都会让你离开这个区域。如果同事问你一个问题,导致 1 分钟的中断,但这会严重影响你,以至于你需要半个小时才能再次提高工作效率,那么你的整体工作效率就会遇到严重的麻烦。如果你处于一个嘈杂的牛棚环境中,就像咖啡因的网络公司喜欢创造的那种环境,营销人员在程序员旁边打电话尖叫,你的生产力就会直线下降,因为知识工作者一次又一次地被打断,永远不会进入这个区域。
对于程序员来说,这尤其困难。生产力取决于能否同时处理短期记忆中的许多小细节。任何形式的中断都可能导致这些细节崩溃。当你恢复工作时,你不记得任何细节(比如你正在使用的局部变量名称,或者你在实现该搜索算法时所处的位置),你必须不断查找这些东西,这会减慢你的速度,直到你恢复速度。
这是简单的代数。比方说(证据似乎表明),如果我们打断一个程序员,哪怕是一分钟,我们真的会浪费 15 分钟的生产力。在这个例子中,让我们把两个程序员 Jeff 和 Mutt 放在一个标准的 Dilbert 小牛肉育肥场的开放式隔间里。Mutt 不记得 strcpy 函数的 Unicode 版本的名称。他可以查一下,这需要 30 秒,或者他可以问 Jeff,这需要 15 秒。由于他就坐在杰夫旁边,他问杰夫。Jeff 分心并失去了 15 分钟的工作效率(为 Mutt 节省了 15 秒)。
现在让我们把它们搬到有墙和门的独立办公室里。现在,当 Mutt 不记得那个函数的名称时,他可以查找它,这仍然需要 30 秒,或者他可以问 Jeff,现在需要 45 秒,并且需要站起来(考虑到程序员的平均身体素质,这不是一件容易的事!于是他查了一下。所以现在 Mutt 损失了 30 秒的生产力,但我们为 Jeff 节省了 15 分钟。啊!
9. 你使用金钱能买到的最好的工具吗?
用编译语言编写代码是最后一件事,仍然无法在花园品种的家用计算机上立即完成。如果您的编译过程需要几秒钟以上,那么获得最新最好的计算机将节省您的时间。如果编译只需要 15 秒,程序员就会在编译器运行时感到无聊,这会让他们陷入困境并扼杀数小时的生产力。
使用单个监视器系统调试 GUI 代码即使不是不可能,也是痛苦的。如果您正在编写 GUI 代码,两个显示器将使事情变得容易得多。
大多数程序员最终必须操作图标或工具栏的位图,而大多数程序员没有可用的好位图编辑器。尝试使用 Microsoft Paint 来操作位图是一个笑话,但这是大多数程序员必须做的。
一流的开发团队不会折磨他们的程序员。即使是因使用功能不足的工具而引起的小挫折也会加起来,使程序员脾气暴躁和不开心。一个脾气暴躁的程序员是一个没有生产力的程序员。
除此之外,还要补充...程序员很容易通过向他们提供最酷、最新的东西来贿赂他们。这是让他们为您工作比实际支付有竞争力的薪水便宜得多的方式!
10. 你们有测试人员吗?
如果你的团队没有专门的测试人员,每两三个程序员至少有一个,你要么在运送有缺陷的产品,要么你浪费了钱。吝啬测试人员是一种令人发指的虚假经济,以至于我被更多的人不承认它所震撼。
11. 新应聘者在面试时会写代码吗?
你会聘请魔术师而不让他们给你展示一些魔术吗?当然不是。
你会在不品尝他们的食物的情况下为您的婚礼聘请餐饮服务商吗?我怀疑。(除非是玛吉阿姨,如果你不让她做她“有名”的切碎的肝蛋糕,她会永远讨厌你)。
然而,每天,程序员都是根据令人印象深刻的简历或面试官喜欢与他们聊天而被聘用的。或者他们被问到琐事问题(“CreateDialog() 和 DialogBox() 有什么区别?”),这些问题可以通过查看文档来回答。你不在乎他们是否记住了数千个关于编程的琐事,你关心他们是否能够编写代码。或者,更糟糕的是,他们被问到“啊哈!”问题:当你知道答案时,这些问题似乎很容易,但如果你不知道答案,它们就是不可能的。
12. 你们做走廊可用性测试吗?
走廊可用性测试是你抓住走廊上下一个经过的人,强迫他们尝试使用你刚刚写的代码。如果你对五个人这样做,你将学到 95% 的关于代码中可用性问题的知识。
好的用户界面设计并不像你想象的那么难,如果你想让客户喜欢和购买你的产品,这一点至关重要。你可以阅读我关于UI设计的免费在线书籍,这是一本简短的程序员入门书。