愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

《人月神话》学习笔记(一):焦油坑

一、何谓焦油坑

“无论你是谁,无论你是否强大,只要陷入焦油坑,就难以自拔,束缚到底”

史前史中,任何巨型猛兽,陷入了焦油坑就会越挣扎越被焦油紧紧缠住。如同大型软件系统的开发,各种团队无论大小、人员是否精干,在面对一个大型系统处理各种相互纠缠和累积一起的问题时,就会很容易使得团队的行动速度变得越来越慢。通过焦油坑这么一个比喻,试图去理解软件系统开发中面临着的问题本质


二、车库的神话

为什么会存在 2 个大神在车库里组成的团队,能够单挑一个十数人组成的研发团队?是否所有的产品都可以只需要 2 个大神,而不用一整个团队?或许应该先了解下编程的产出是何物


三、编程系统产品

编程产物的产出演进,可以用如下这张图表示:

  • 程序: 单个程序员可以产出完整的程序,且这个程序它可以在作者的平台上运行得良好,产出的这个程序可以作为单个程序员生产效率的评估标准
  • 编程产品: 可以被任何人运行、测试、修复和扩展的程序,可运行在多个操作系统上,供多套数据使用。也就是说,如果一套程序要转化为编程产品,那么它需要遵循一定的规范和标准,并且需要考虑好边界输入、经过彻底的测试来保证其健壮性,还需要提供完善的文档,以方便他人使用、修复和扩展程序。经验数据表明,编程产品的产出成本,通常至少是测试过程序的三倍
  • 编程系统: 程序要变成变成系统中的一个构件单元,就需要符合整个系统的规范、接口的规范等,如此才能够与其他编程系统相互协作,用来组装和搭建整个系统。由于要与其他系统构件一道组装,那么就会带来不同的组合用例,对这些用例的测试也会带来许多潜在的bug,继而带来修缮的成本。因此,在程序完善为编程系统的时候,也会带来至少三倍的成本。
  • 编程系统产品: 编程系统产品是系统开发的最终目标,它是完善的、真正有用的,一个程序要变成编程系统产品,就需要经过编程产品编程系统的演变,而这会带来复合起来高达九倍的成本

为了更好的理解以上概念,我们举个例子:

假设有一个除法计算器程序,它能够完成两数相除求结果的计算

  • 程序员可以开发出除法程序,它已经处理了一些边界,比如除数不能为零,能够正确返回结果。那么这是一个完整的程序。但是它还不足以作为一个产品交付,毕竟我们还不能确保它能够被各个用户使用的时候,能够有一致的使用体验和上手体验。
  • 那么,作为一个编程产品,我们可能还需要制定一些规范,如输出结果必须保留2位小数、良好的提示语(如除数为0时的提示语),QA们还需要投入测试,测试各种输入会潜在的问题,比如输入非数字会怎么样,输入负数、小数等等会怎么样,以及在其他操作系统平台上能否良好运行……在经过完整的测试后,产品经理还需要编写用户手册,以指导用户如何使用这个程序。在历经诸如此类流程过后,程序才能够变成一个编程产品,是可以被其他人使用、测试和扩展的
  • 但是如果考虑到将这个除法器整合到一个完整的计算器中的时候,那么这个程序可能还需要遵循计算器的输入输出规范、接口规范、整合规范等,那么在整合组装过程中,就需要做一些额外的修缮工作,此后方能够成为编程系统
  • 在嵌入到计算器中构成整个系统时,我们可能还需要以编程产品的要求来重新梳理一遍流程,而这也会带来额外的测试用例和整合成本等,经过这些步骤之后,最终才能成为编程系统产品

因此,通过以上概念的介绍,我们相信车库中可以产出良好的程序,但是在程序编程系统产品发展的过程中,车库大神们往往也会觉得力不从心(现实世界中,不难见到那些最终因为无法持续维护而走向没落的开源程序),因为产品化、系统化的过程中,耗费的时间和精力是数倍的增加,这也是为什么需要一个完整研发团队的原因,因为我们需要的是最终可交付的产品,但程序往往是不够的


四、程序员的乐趣与烦恼

乐趣:

  • 程序员享受作为造物主的快乐
  • 程序员享受创造出的万物,为人所使用、所歌颂时的兴奋感
  • 程序员享受这种魔术般的过程,享受将这个系统巧妙组装的快乐,享受得到预期结果的魅力
  • 程序员享受学习的乐趣,乐于面临挑战,并且收获解决问题带来的快感
  • 编程是思考的产物,程序员只需单纯工作在思考之中,写代码犹如诗人写诗。很少有这种介质,可以如此灵活地将思考表达出来,传递出来。但编程比写诗歌更实在,它是可以移动和运行的,可以发声和显形的,这种犹如魔术般的变换,十足地有趣

烦恼:

  • 必须追求完美,程序不容许有错误,编写错误的程序犹如念错的咒语,魔法不会如期出现
  • 工作中可能需要应对由他人设立的目标和方向,依赖于其他人的资源。不能够随心所欲地控制工作环境和工作目标,因此会有个人权威难以匹配所承担的责任的情况,个人权威的体现在于每次工作任务的圆满完成
  • 所工作的编程系统依赖他人时,不得不花时间研究和修改他人的产物,这些产物可能是设计不合理的、实现拙劣的、文档匮乏的,这种对他人的依赖是非常痛苦的
  • 实现的过程是有趣的,但寻找和修复BUG的过程却是无聊的。而伴随实现的过程,也往往有着枯燥沉闷的时间和艰苦的劳动
  • 调试和差错具有不确定性的复杂度,寻找最后一个错误比第一个错误所花费的时间更多
  • 最糟糕的情况是,投入大量时间和精力所开发出来的产品系统,却可能在面世的时候显得陈旧过时,面临着竞争对手更先进的设计方案的挑战


总结

编程,可能是一个另许多人痛苦挣扎的焦油坑,但也是乐趣与烦恼共存的创造性活动。但对大多数人而言,编程的乐趣远大于烦恼。虽然我们在开发系统的过程中会很难避免遇到焦油坑,但好在我们可以站在巨人的肩膀上,通过对一些软件工程理论知识的学习,就能够掌握通过这些焦油坑的技巧,为我们的实践提供指导