推荐理由
作者Frederick P. Brooks,是北卡罗莱纳大学Kenan-Flagler商学院的计算机科学教授。他曾荣获图灵奖,美国计算机协会(ACM)称赞他“对计算机体系结构、操作系统和软件工程做出了里程碑式的贡献。”
作为软件工程领域的重要著作,《人月神话》结合工业界具体的大型系统开发实例,对软件开发领域的诸多问题提出了思考和见解,许多论断被软件开发从业者奉为圭臬。经过数十年的时间淬炼,对今天的大型软件开发都有启发意义。
本书要点
- 焦油坑:大型系统开发中各种问题缠绕和积累在一起,使得大型系统的开发十分困难。
- 人月神话:在软件开发领域,用人月作为工作规模的衡量指标并不适用。
- 外科手术式队伍:软件开发团队可以参照外科手术式队伍组成、运作、扩建
- 贵族专治、民主政治和系统设计:在系统设计中,概念完整性应该是最重要考虑的因素
- 画蛇添足:架构师和项目经理都需要避免second-system effect
- 贯彻执行:定义良好的规格说明是重要的,会议、测试小组等形式是保证设计执行的良好方式。
- 为什么巴比伦塔会失败?:软件团队的交流和组织是软件开发成败的关键
- 胸有成竹:对大型软件系统产品的开发所需的时间和资源进行准确的估测,能让我们在项目进度和前景胸有成竹
- 削足适履:最大化资源利用率;巧妙的数据结构
- 提纲挈领:文档是重要和必要的
- 未雨绸缪:只有“变化“是不变的,为需求和设计的变化做准备
- 干将莫邪:项目经理需要为软件开发团队配备完备的工具
- 整体部分:好的自顶向下的设计避免缺陷
- 祸起萧墙:软件开发团队需要为计划和控制投入资源
- 另外一面:提供给用户的使用说明等文档是软件呈现给用户的另外一面
- 《没有银弹》:由于软件的复杂性,一致性,变化性和不可见性,解决软件危机的银弹并不存在
- 再论《没有银弹》:人们期待中的重大突破不可能在近期内到来
精编书摘
焦油坑
过去几十年的大型系统开发犹如焦油坑,各种团队一个接一个淹没在焦油坑中。表面上没有任何一个单独的问题导致困难,当他们相互缠绕和累积在一起的时候,团队的行动就会变得越来越慢。如果想看清这个问题的本质,就必须试图先去理解它。
编程系统产品是大多数系统开发的目标,然而它的成本是程序的9倍。
编程的乐趣在于:编程是一种创建事物的纯粹快乐;快乐来自于开发对其他人有用的东西;整个过程体现出魔术般的力量;学习的乐趣;工作在如此易于驾驭的介质上。
编程的苦恼在于:必须追求完美;由他人来设定目标,供给资源,提供信息;概念性设计是有趣的,但寻找琐碎的bug却只是一项重复性的活动;调试和查错是往往是线性收敛的;产品在完成时可能就已经过时。
人月神话
软件项目中缺乏合理的时间进度的主要原因是:
对估算技术缺乏有效的研究
采用的估算技术隐含的假设人和月可以互换,错误的将工作量与进度相互混淆
软件经理由于对自己的估算缺乏信心,往往不会有耐心持续的进行估算这项工作
对进度缺少跟踪和监督
当意识到进度的偏移时,下意识的反应是增加人力
编程人员的乐观主义并不应该是理所应当的
用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话,在软件开发项目中,由于任务在次序上的不可分解、培训和交流的需要,人月并不适用。
在早期进度策划时,允许充分的系统测试时间是非常重要的。
Brooks法则:
向进度落后的项目中增加人手,只会使进度更加落后。
外科手术式队伍
外科手术式队伍的组成:外科医生(首席程序员)、副手、管理员、编辑、两个秘书、程序职员、工具维护人员、测试人员、语言专家。
外科手术式队伍的运作:
首席程序员和副手都了解所有的设计和全部的代码,节省了空间分配、磁盘访问等的劳动量,同时也确保了工作概念上的完整性。
不存在利益上的差别,观点不一致由首席程序员单方面来统一。
剩余人员职能的专业化分工是高效的关键,使成员之间采用非常简单的交流模式成为可能。
外科手术式队伍的扩建成功依赖于这样一个事实:每个部分的概念完整性得到了彻底的提高。
贵族专治、民主政治和系统设计
在系统设计中,概念完整性应该是最重要考虑的因素
概念完整性的获得:
每个部分必须反映相同的原理、原则和一致的折衷机制。在语法上,每个部分应使用相同的技巧;在语义上,应具有相同的相似性。
对于非常大型的项目,将设计方法、体系结构方面的工作与具体实现相分离是获得概念完整性的强有力方法。
外部的体系结构规定实际上是增强, 而不是限制实现小组的创造性。
整个创造性活动包括了三个独立的阶段: 体系结构( architecture)、 设计实现( implementation)、 物理实现( realization)。 在实际情况中,它们往往可以同时开始和并发地进行。
同工作的水平分割相比, 垂直划分从根本上大大减少了劳动量, 结果是使交流彻底地简化,概念完整性得到大幅提高。
画蛇添足
架构师的交互准则和机制:
牢记是开发人员承担创造性和发明性的实现责任,所以架构师只能建议而不能支配
时刻准备着为所指定的说明建议一种实现的方法,同样准备接受其他任何能达到目标的方法。
对上述的建议保持低调和平静
准备放弃坚持所作的改进和建议
架构师如何避免画蛇添足--开发第二个系统所引起的后果(second-system effect)?
有意识关注那些系统的特殊危险, 运用特别的自我约束准则, 来避免那些功能上的修饰
根据系统基本理念及目的变更, 舍弃一些功能
项目经理如何避免画蛇添足(second-system effect)?
他必须坚持至少拥有两个系统以上开发经验结构师的决定。 同时, 保持对特殊诱惑的警觉, 他可以不断提出正确的问题,确保原则上的概念和目标在详细设计中得到完整的体现。
贯彻执行
手册、或者书面规格说明,是一个非常必要的工具,尽管光有文档是不够的。
会议是必要的,我们把会议分成两个级别: 周例会和年度大会——这实际上是一种非常有效的方式
设立测试小组是使设计决策得以贯彻执行的必要手段, 同样也是需要尽早着手,与设计同时实施的重要环节
为什么巴比伦塔会失败?
团队相互之间的交流沟通的可能的途径有:
非正式途径;会议;工作手册
编程人员仅了解自己负责的部分,而不是整个系统的开发细节时,工作效率最高。 这种方法的先决条件是精确和完整地定义所有接口。这的确是一个彻底的解决方法。如果能处理得好,的确是能解决很多“灾难“。一个好的信息系统不但能暴露接口错误,还能有助于改正错误
交流和交流的结果——组织, 是成功的关键。 交流和组织的技能需要管理者仔细考虑, 相关经验的积累和能力的提高同软件技术本身一样重要
胸有成竹
对大型软件系统产品的开发所需的时间和资源进行准确的估测,能让我们在项目进度和前景胸有成竹。软件代码的开发效率和代码模块之间所需的交互相关。界面交互复杂的程序需要更多的测试和调试时间,单纯地增加人手并不能有助于开发效率的提高。
削足适履
同任何开销一样, 规模本身不是坏事,但不必要的规模是不可取的
创造出自精湛的技艺,精炼、充分和快速的程序也是如此。技艺改进的结果往往是战略上的突破, 而不仅仅是技巧上的提高
更普遍的是,战略上突破常来自数据或表的重新表达——这是程序的核心所在
提纲挈领
软件项目的关键文档:目标;产品技术说明;进度表;预算;工作空间分配;组织图
正式文档的必要性:书面记录决策是必要的;文档能够作为同其他人的沟通渠道;项目经理的文档可以作为数据基础和检查列表
未雨绸缪
目标上的一些变化无可避免,事先为它们做准备总比假设它们不会出现要好得多。 不但目标上的变化不可避免, 而且设计策略和技术上的变化也不可避免。 抛弃原型概念本身就是对事实的接受——随着学习的过程更改设计
系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵) 的过程, 即使是最熟练的软件维护工作, 也只是放缓了系统退化到非稳态的进程
干将莫邪(sharp tools)
项目经理必须考虑、计划、组织的工具有:
计算机设施,需要硬件和使用安排策略
操作系统,提供服务的方式必须明了
语言,语言的使用方针必须明确
实用程序、调试辅助程序、测试用例生成工具和处理文档的字处理系统
整体部分
许许多多的失败完全源于那些产品未精确定义的地方。
好的自顶向下设计从四个方面避免了 bug。
首先, 清晰的结构和表达方式更容易对需求和模块功能进行精确的描述;
其次, 模块分割和模块独立性避免了系统级的 bug。
另外, 细节的隐藏使结构上的缺陷更加容易识别。
第四,设计在每个精化步骤的层次上是可以测试的,所以测试可以尽早开始,并且每个步骤的重点可以放在合适的级别上。
祸起萧墙
好的里程碑对团队来说实际上是一项服务,可以用来向项目经理提出合理要求的一项服务, 而不确切的里程碑是难以处理的负担。
对计划和控制职能进行适度的技术人力投资是非常值得赞赏的。它对项目的贡献方式和直接开发软件产品有很大的不同
另外一面
对于软件编程产品来说, 程序向用户所呈现的面貌与提供给机器识别的内容同样重要
程序修改人员所使用的文档中, 除了描述事情如何以外, 还应阐述它为什么那样。对于加深理解,目的是非常关键的,但即使是高级语言的语法,也不能表达目的
没有银弹
所有软件活动包括根本任务——打造由抽象软件实体构成的复杂概念结构,次要任务——使用编程语言表达这些抽象实体, 在空间和时间限制内将它们映射成机器语言。
软件开发中困难的部分是规格化、设计和测试这些概念上的结构,而不是对概念进行表达和对实现逼真程度进行验证
现代软件系统中复杂度、一致性、可变性和不可见性是无法规避的。
银弹的希望:Ada和其他高级编程语言;面向对象编程;人工智能;专家系统;“自动”编程;图形化编程;程序验证;环境和工具;工作站。
针对概念上根本问题的颇具前途的方法:
购买和自行开发;需求精炼和快速原型;增量开发--增长,而非搭建系统;卓越的设计人员
再论《没有银弹》
《 没有银弹》 提出了全力解决复杂性问题的方法, 这种方法可以在现实中取得十分乐观的进展。 它倡导向软件系统增加必要的复杂性:层次化,通过分层的模块或者对象;增量化,从而系统可以持续地运行