这是一本老书,作者 Steve Maguire 在微软工作期间写了这本书,英文版于 1994 年发布。我们看到的标题是中译版名字,英文版的名字是《Debugging the Development Process》,这本书详细阐述了软件开发
过程中的常见问题及其解决方案,强调团队合作、项目管理和开发流程的优化。该书成为软件开发和项目管理领域的经典著作,受到了广泛的认可和赞誉。
不记录,等于没读。
通过积极学习,提高团队成员的技术水平是很好的。团队领导者还需要做的一件事情是:纠正错误态度,促进有益态度。新的态度会影响程序员将要完成的所有工作。本章探讨一些常见的程序员态度,这些态度对项目成功不利:
- BUG 是不可避免的
- 我以后再修复 BUG
- 按照正确方式做事会花费太多时间
- 这样对用户来说已经足够了
- 给用户提供一些东西总比什么都不给好
- 我们做我们的事,你做你的事
- 这只是内部使用
- ……
在上一章,我强调学习的重要性,组员应该对技术和知识精益求精。但还有一种能带来最深刻的改进,那就是当团队对开发产品采取新的态度时。
对待 BUG 的态度
业界公认的一个错误观念是:程序 BUG 是无法避免的。这是大错特错。
作者的第一本书就是教授如何写出零错误程序的,这本书的名字是《编程精粹—— Microsoft 编写优质无错 C 程序秘诀》,本博客也有这本书的读书笔记。总结起来,编写零错误程序可能会使用到如下技术:
- 善用检测到更多错误的方法:比如启用所有可选的编译器警告、使用语法和可移植性检查工具等。
- 设计并使用断言:用户在错误发生时,可以自动地把它们检查出来。相比编译器等工具,它能够检查出更多的错误。
- 子系统完整性检查:它能主动验证子系统,在错误影响程序之前发现错误。针对标准 C 内存管理器的完整性检查能够检测空指针、内存泄漏以及非法使用未初始化或已释放的内存。
- 对才程序单步跟踪:在最有可能出现错误的时候,密切关注。找到错误的最佳方法是使用调试器逐步执行所有新代码。
- 精心设计接口:函数只是无错还不够,函数还必须易于使用,且不会引入意外的 BUG。
- 当函数有多种实现可能性,用已被证明同样高效但更安全的替代方案,来取代那些风险较高的算法和语言习惯。比如,使用有严格定义的数据类型、避免无关紧要的 if 语句、消除不一致等。
- 识别并避开危险的编码实践,比如避免引用刚释放的内存、避免使用全局或静态变量传递数据、避免使用寄生函数等。
- 正确的态度和一套良好的编程习惯。
通过额外的努力,“零错误”程序是可以实现的。程序员要有正确的态度:没有任何理由,有 BUG 就是不行。
在我的项目中,我会仔细追查 BUG 清单上的每一个 BUG,看看这个 BUG 是不是应该早在单元测试阶段就应该发现,或是在用除错工具追踪时就该被找出来。 如果是程序设计师粗心,让这个早在开发时期就能发现的错虫留到整个系统构建完毕时才被发现,我就会认为他的工作质量不及格,应该再重新训练。
所以应该多花功夫用各种方法做最彻底的测试。要保证测试工作毫无疏漏、每种情况都测到。
对待调试代码的态度
- 即使你已经觉得程序不可能有错,还是值得加上调试代码;
- 对于加上调试代码这件事,永远不能认为“太费时间”或是“太困难”,这都是借口。
凡事不能的态度
当向团队成员下达一项任务时,要提防对方有“太费时间”、“太困难”的反映。培训程序员首先考虑任务是否有意义,以及它是否与项目目标和优先级相匹配。
凡是不能的态度,对于解决问题与创造力是极大的伤害,我的部门里有一个不成文规定,所有人都不准说“某件事不可能做到“,他们可以说很难或很花时间。当某人说“某件事不可能做到”时,他往往是错的。作者认为人们之所以会说“某件事不可能做到”,只是因为这件事超出了他们的经验范围。即使是最优秀的团队,也会对未知的事情恐惧和排斥。
如果一个人不想做某件事,通常不是由于客观条件不允许,而是他有下面四种心态之一:恐惧、排斥、自卑、怠惰。
—— 《不要对自己撒谎》
温伯格在《咨询的奥秘》中讲过“橙汁测试”的故事,他通过了“橙汁测试”,然后拿到了咨询合同:客户请温伯格负责挑选一个年度销售大会的场地,得容纳 700 人。在开会期间,每天的早餐必须喝橙汁,这是他们的传统。想想准备 700 人的早餐,这一项就够难了,但更难的是早餐必须在 7 点整准时开始,还必须每人都得有一大杯鲜榨橙汁。必须是鲜榨,从榨出来到端上餐桌不能超过 2 个小时。
那些不能通过“橙汁测试”的人,要么说“这可办不到”,要么说“这没问题”,想着先拿到生意再说。温伯格通过了测试,他的回答是:“这真是个问题。我可以帮你……这是所需的费用。”
问题总有解决办法,不同的只是代价。顾问不应该替客户决定要不要花费这个代价,而是应该告知方案和方案的代价,由客户决定是否实施。“橙汁测试”重新归纳后是:我们能做。这是所需的费用。
作为管理者,要鼓励组员提出问题,哪怕这个问题暂时没办法解决。管理者不能强制让提出问题的人解决问题,这样会造成没人再提问题。想想看,如果核电站的工作人员发现反应炉边流出绿色的粘稠物,他会因为自己无法解决就只有闭口不提吗?他也许不知道怎么办,但是别人知道啊,至少应该尽快想办法处理。如果问题连提都没有提出来,那才是永远无法解决的。
这样已经够好了
作者认为程序使用者才更会关注速度和质量问题,因为他们是真正与软件利害相关的人,程序编写者反而不是。所以如果程序员给你说:“这对使用者来说已经够快了吧。”那么这些程序员就是没有意识到他们这么说是没有任何依据的。
给用户一个速度慢、经常崩溃的功能会比完全不给好吗?至少用户可以应急使用?作者认为这样做不好。用户并不能体谅”有总比没有好“的用意,他们满怀期望,拆开包装、执行软件后,发现功能远不及预期,心中反而会产生不满和抱怨。所以,如果一个功能没有达到理想程度时,不要给用户使用。用户既然从未曾拥有,也就谈不上失去。宁愿延期交货,也要务必追求质量完美。
产品的整体观
长久以来,微软的“程序语言部”里,把编译器、调试器、链接器 等等程序语言的软件分别当作完全不同的产品。全世界的程序设计师都要求改善调试器、提高链接器速度。但程序语言部认为编译器才是最重要的,调试器、链接器只不过是个辅助工具。客户肯定不会这么想,对他们来说,所有的东西都是同一个产品,如果其中一个有短板,用户可能会放弃整个产品。
最后,程序语言部终于获得整合,把自己的产品定位为“程序开发环境”,而不是编译器。结果 Visual C++,一个令世人耳目一新的产品,一个令微软的程序语言部改头换面的产品,才在这样的理念中诞生。
在包装盒里的每一件东西,都是产品的一部分。
重复就是浪费
作者开发工作有一个原则:凡是别人写好、测试通过,而我可以使用的程序,我一定二话不说就把他的程序抓过来用。基于这样的态度,我在开发自己的程序时,总是尽可能为潜在使用者设想,写出一个别人可以使用的程序。编写新功能最好的方法是引用别人已经测试通过的程序,也就是程序代码的重复使用 。虽然大部分的程序设计师都很认同这一点,但是他们潜意识里觉得别人写的程序很难拿来使用。
程序员应该培养新的态度:注意自己写的程序是否具有可重用性。要满足这一点,程序设计师就会尽量减少子程序与主程序之间的关联性,让子程序独立。
要点
写出“零错误”程序很困难,但并非不可能,需要多下点功夫才能做到,程序设计师在将程序送交测试小组之前,应该花更多时间测试他们的代码。程序设计师要使用一切办法侦测和预防错误。
小心那种“太难了”、“太花时间”或是“太麻烦”的本能反应。当遇到别人有这种反应,请先问自己他有没有认真思考过这件事的重要性、是否符合项目目标。如果你认为他其实未经深思熟虑,只是直觉反应,那你就应该把你的想法告诉他,请他重新评估,也许就会有公平的答案。
人们遇到经验范围之外的事情,通常会消极对待,会认为“这完全不可能”。会强烈反对。试着消除这种习惯性的反应,设法给组员灌输“只要花时间想想看,大部分的事情都做得到”的观念。不妨这个问题来对付“凡是不能”的态度:“我了解这是做不到的,但是如果做得到,那你会怎么做?”然后你就会发现惊人的转变。
每一份打赏,都是对创作者劳动的肯定与回报。!