第10章 未雨绸缪
在化学领域中,在实验室可以进行的反应过程,并不能在工厂中一步实现。一个被称为“ 实验性工厂(pilot planet)”的中间步骤是非常必要的,它会为提高产量和在缺乏保护的环境下运作提供宝贵经验。软件系统设计中也同样有这方面的问题,若把设计的算法应用到待发布的软件中,根据时间进度把第一次开发的产品发布给客户,显然这是非常糟糕的事情。
因此,管理上的问题变成了“是否预先计划抛弃原型的开发,或者是否将该原型发布给用户?”,将原型发布给用户,可以获得时间,但是它的代价高昂——对于用户,使用极度痛苦;对于重新开发的人员,分散了精力;对于产品,影响了声誉,即使最好的再设计也难以挽回名声。
首先,我们要意识到,变化是与生俱来的,实验性的系统必须被构建和丢弃。那么,该如何为上述变化设计系统呢?这其中最重要的措施是使用高级语言和自文档技术,以减少变更引起的错误。采用编译时的操作来整合标准声明,在很大程度上帮助了变化的调整。此外,当系统发生变化时,管理结构也需要进行调整,我们还需要变更计划组织架构。
在程序发布给用后,变化仍将继续。对于一个广泛使用的程序,其维护总成本通常是开发成本的40%或更多,维护成本受用户数目的严重影响,用户越多,所发现的错误也越多。Campbell指出了一个显示产品生命期中每月bug数的有趣曲线,它先是下降,然后攀升。缺陷修复总会以(20-50)%的机率引入新的bug。
图3 出现bug数量是发布时间的函数
在每次修复之后,必须重新运行先前所有的测试用例,从而确保系统不会以更隐蔽的方式被破坏。同样,设计实现的人员越少、接口越少,产生的错误也就越少。系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵)的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化到非稳态的进程。
第11章 干将莫邪
这里要给大家科普一下,干将莫邪(ye,第二声)不是一个将士叫莫邪,更不是王者荣耀里的干将莫邪。干将是春秋楚国的一名铁匠,奉楚王之命造剑,后其与妻子莫邪铸成宝剑两把,一曰干将,一曰莫邪。在干将将雌剑献与楚王之后,便被楚王杀害,其子之后完成父愿,用雄剑将楚王刺杀为父报仇。这一传说赞颂了剑工高超的技艺,宝剑文字的神采和少年的壮烈,批判了统治者的残暴。
本章当然是借干将莫邪高超的铸剑技艺来告诫项目经理:软件开发仅有通用工具是远远不够的,他们应该制订一套策略,以及为通用工具的开发分配资源,与此同时,他还必须意识到专业工具的需求。项目经理必须考虑、计划、组织的工具有目标机器、辅助机器和数据服务、高级语言和交互式编程,来为专业需要和个人偏好制定更多专业的工具。
第12章 整体部分
经过以上十二个章节的讨论,我们现在来探讨下如何开发一个可以运行的系统?如何测试系统?如何将经过测试的一系列构件集成到已测试过、可以依赖的系统?
Bug在我们开发中难免会遇到,而产品的概念完整性在使它易于使用的同时,也使开发更容易进行以及 Bug 更不容易产生。细致的功能定义、详细的规格说明、规范化的功能描述说明以及这些方法的实施,大大减少了系统中必须查找的 bug 数量。
为了剔除Bug,作者给出了测试规格说明、自顶向下的设计、结构化编程三个建议。程序调试整体看来有四个步骤:本机调试、内存转储、快照、交互式调试。软件系统开发过程中出乎意料的困难部分是系统集成测试。系统调试花费的时间会比预料的更长,需要一种完备系统化和可计划的方法来降低它的困难程度。作者建议使用经过调试的构件单元,系统集成调试要求在每个部分都能正常运行之后开始;搭建充分的测试平台,产生相当于测试对象一半代码量的供调试使用的所有程序和数据也不足为奇;对测试期间进行严格控制;一次只添加一个构建;变更阶段化、定期变更。
第13章 祸起萧墙
千里之堤毁于蚁穴,一天一天的进度落后是难以识别、不容易防范和难以弥补的,项目进度也经常以一种难以察觉,但是残酷无情的方式慢慢落后。
这一点我们作为学生应该体会很深刻,当我们打开教辅系统,发现今天的作业只有两门,而截止日期在一周后,我们会怎样做?那当然是选择原谅他了,打开Dota、吃鸡,搞一搞自己感兴趣的研究,看看视频等待。在等到提交作业前,我们会发现不仅这两个作业量难以在短时间内完成,而且我们作业由两个变成了四个!特别是对于我们USTCer,给你喘息机会是不存在的,由于开始的懈怠或者延误,将导致你之后的作业都会晚于预期完成。
软件开发亦是如此,那么我们该如何有效地预防这个问题呢?根据一个严格的进度表来控制项目,其中第一个步骤是制订进度表。里程碑的选择只有一个原则,那就是,里程碑必须是具体的、特定的、可度量的事件,能够进行清晰定义。对于里程碑的结果,只有达到和未达到两种,不能说是90%、99%完成了。
作为程序的开发者,我们应该是进取的,关心每一天的滞后,因为它们是大灾祸的基本组成元素。作为项目经理,让老板知道地板下的污垢——项目进度上的问题,无论是减少角色冲突和鼓励状态共享,或是直截了当的展示,这一点对预防项目滞后也是非常有帮助的。
第14章 另外一面
公共应用程序的用户在时间和空间上都远离它们的作者,因此对这类程序,文档的重要性更是不言而喻!对软件编程产品来说,程序向用户所呈现的面貌和提供给机器识别的内容同样重要。
现实中可能经常会出现这样的现象,在团队与客户交付的会议中,技艺高超的程序员向客户“哐哐哐”展示产品技术细节,客户往往听得一头雾水,而产品经理则会用相对不那么“技术”的话语来向客户阐述,客户便恍然大悟。这里,我们可以将技艺高超的程序员理解为计算机程序,是人与机器交互的信息;产品经理则是需求文档,代表了程序与用户间的交互。
文档的必要性不言而喻,问题在于什么样的文档才是好的文档?不同用户需要不同级别的文档,每个用户都需要一段对程序进行描述的文字,这其中包括:目的、环境、范围、实现功能和使用的算法、输入-输出格式、操作指令、选项、运行时间、精度和校验。除了程序的使用方法,还必须附带一些程序正确运行的证明,即测试用例。调整程序或者修复程序则需要更多的信息,修改者需要一份清晰的系统的内部结构信息,这将包括:流程图或子系统的结构图、对所用算法的完整描述、对所有文件规划的解释、数据流的概要描述、初始设计中,对已预见修改的讨论;特性、功能回调的位置以及出口;原作者对可能会扩充的地方以及可能处理方案的一些意见。
值得注意的是,为了使文档易于维护,将它们合并至源程序是至关重要的,而不是作为独立文档进行保存。
第15章 没有银弹——软件工程中的根本和次要问题
人狼的传说中,人狼是一种具有人和狼两种特征的恐怖生物,而银弹是消灭它的一种最有效的子弹。作者将软件开发比作人狼,而将提高软件开发效率的方法比作银弹。作者预言未来十年,想要试图通过寻找一种有效地银弹将软件开发效率提高一个甚至几个数量级,这种银弹不可能出现。
所有软件活动包括根本任务——打造由抽象软件实体构成的复杂概念结构,次要任务——使用编程语言表达这些抽象实体,在空间和时间限制内将它们映射成机器语言。软件工程领域的根本难题在于复杂度、一致性、可变性和不可见性。文中罗列了一些可能的银弹,如Ada 和其他高级编程语言、面向对象编程、人工智能等,这些都只能解决软件工程中的非本质困难,而对于软件工程根本的问题于事无补。就是说,我们某种程度上能够解决使用编程语言表达抽象的实体,或者将其变得结构化,构建起完整的概念结构,但是仍然没有解决软件工程的“复杂度、一致性、可变性和不可见性”这一根本难题。
现在的技术中最有希望的,并且解决了软件的根本而非次要问题的技术,是开发作为迭代需求过程的一部分——快速原型化系统的方法和工具。这是因为快速原型有助于澄清软件工程的概念结构,从而降低了后期变更的幅度。基于快速原型进行增量开发,目前已经成为实际开发的标准流程。快速原型化方法是一种增量方法,是一种自外向内型的设计模式。在开发真实系统之前,构造一个原型,通过用户和软件开发人员之间的交互,在该原型的基础上,逐渐完成整个系统的开发工作。
第16章 再论《没有银弹》
自从《没有银弹》发表以后,遭到了大量的误解、批评和质疑,作者又专门写了这篇文章来继续解释他的观点和回应批评,这里提到了很多潜在的银弹。
例如Harel提出的一种叫做Vanilla的框架,Jone的质量带来生产率的观点、面向对象这枚“铜弹”、软件重用等,这些到现在看来并未称为一枚真正意义上的银弹。最后Brooks总结说这枚银弹的本质并未改变,我们依旧没法找到这枚银弹,现在是从业者研究和分析革命性进展的时刻,而不是等待或希望它的出现。
第17章 《人月神话》的观点:是或非?
这里,作者Brooks回顾了1975年版《人月神话》中那些被推翻和被支持的观点。他将它们表达成刻板的形式是希望能引起读者的思考、判断和讨论。
本章类似于一本观点手册,这里便不一一例举,大家有兴趣的话可以翻阅看看。
第18章 20年后的人月神话
本章作为上一章的2.0版本,站在20年后的角度来看当年的一些观点。
概念完整性和结构师。概念完整性是产品质量的核心。拥有一位结构师是迈向概念完整性的最重要一步。这个原理决不仅限于软件系统,它适用于所有的复杂事物,如计算机、飞机、防御系统、全球定位系统等。
开发第二个系统所引起的后果:盲目的功能和频率猜测。
图形(WIMP)界面的成功。在过去 20 年内,软件开发领域中,令人印象最深刻的进步是窗口(Windows)、图标(Icons)、菜单(Menus)、指针选取(Pointing)界面的成功——或者简称为 WIMP。这些在今天是如此的熟悉,以致于不需要任何解释。
没有构建舍弃原型——瀑布模型是错误的!瀑布模型的基本谬误是它假设项目只经历 一次 过程,而且体系结构出色并易于使用,设计是合理可靠的,随着测试的进行,编码实现是可以修改和调整的。瀑布模型的第二个谬误是它假设整个系统一次性地被构建,在所有的设计、大部分编码、部分单元测试完成之后,才为闭环的系统测试合并各个部分。
增量开发模型更佳——渐进地精化。文中列举了构建闭环的框架系统、Parnas 关于搭建一棵相关产品的家族树、Microsoft 的“每晚重建”方法、增量式开发和快速原型,这些都对如今的软件工程领域产生了极大的影响。
关于信息隐藏,作者指出了Parnas 是正确的,自己是错误的。Parnas认为代码模块应该采用定义良好的接口来封装,这些模块的内部结构应该是程序员的私有财产,外部是不可见的。信息隐藏——现在常常内建于面向对象的编程中——是唯一提高软件设计水平的途径。
此外,Brooks还对其他的一些观点进行了总结,并对未来软件工程进行了展望,这里,我只是引用了他文末的最后一段,其余的部分就不一一赘述了,我认为我们应该已经具备新世纪的视角来对现如今的软件工程领域进行独立判断。
“软件工程的焦油坑在将来很长一段时间内会继续地使人们举步维艰,无法自拔。软件系统可能是人类创造中最错综复杂的事物,只能期待人们在力所能及的或者刚刚超越力所能及的范围内进行探索和尝试。这个复杂的行业需要:进行持续的发展;学习使用更大的要素来开发;新工具的最佳使用;经论证的管理方法的最佳应用;良好判断的自由发挥;以及能够使我们认识到自己不足和容易犯错的——上帝所赐予的谦卑。”
至此,《人月神话》一书就大致叙述完毕了,可能存在很多个人的观点和理解错误,欢迎大家指出并提出意见。这里请允许我做一个小小的感悟,《人月神话》并非像很多技术类丛书一样教授我们很多实际的理论知识,它更多的是跟我们交流软件开发中的一些误区和心得。作为程序开发人员(这里就不说是程序猿/媛了),阅读这样的书籍,甚至说是小说,对我们理解工作内容和思考工作方式是大有裨益的。就我个人而言,之前看过《敏捷估计与规划》(Mike Cohn著)一书,实际上,书中的很多理论在人月中的讨论中都有体现。
最后,我希望通过我们不仅是我们IT人士的不断地摸索和交流,不断寻找出一条适合如今软件工程开发的道路,续写这段流传的人月神话。
书籍下载链接:链接:https://pan.baidu.com/s/1ec9108i1jeQdZFFZiRk0sw;提取码:hfbs。
以下两篇博客在本文的写作中提供了一定的见解和总结,在此特别感谢。