没有银弹-《人月神话》读书笔记

2018-04-18

《人月神话》是软件工程界的两本神书之一,另外一本是《人件》,它们被封神的原因可能是:

  1. 都是关于人与团队的书(非具体技术),被淘汰的过程比较慢,软件技术日新月异,但人性变化并不大
  2. 写得比较早,描写也比较深刻,影响了很多技术和工程方法,逐渐被后人推崇

学生时代翻过一次,当时没有项目开发经验,没怎么看懂。如今重头再看,不禁为作者的远见卓识所折服,在快速发展的软件开发领域,一本写于70年代的书直到现在依然有着很大的参考价值。尽管书中一些观点现在已经几乎成为软件工程界的常识,但时时翻看应该还是可以引起不少思考和感悟。

下面这些是阅读本书过程中的一些想法:

  1. 进入编程行业,犹如掉焦油坑,快乐和苦恼并存。烦恼时对照着书想想能自己从编程中得到的快乐和从事这个行业的初衷,兴许会平静不少
  2. 向进度落后的项目中增加人手,只会使进度更加落后。现在依然适用,实践中真正出现问题时,优先完成主要功能必要时舍弃或延缓次要功能
  3. 将体系结构的工作与具体实现相分离是获得概念完整性的强有力方法。现在软件开发中架构和实现相分离很普遍,架构师确实会剥夺负责具体实现的程序员的一部分创造性,并且会有高高在上的感觉,但这却是保证软件能够顺产的关键,要是感觉不平等,就好好从具体实现中找乐趣,或者向架构师方向努力
  4. 尽可能的重用优秀的开源代码,甚至可以购买商业代码二次开发,牢记你的目的是尽快开发出产品,而不是秀自己的技术能力

本书探讨了软件工程领域一系列问题,核心章节是第1、2、3、4、16章,这个版本翻译得不甚通顺,另外因为作者的年代离我们比较远,有些思想现在已经很普通了可以快速跳过,书中有些项目细节也可以略过。下面是读书摘记。

第1章 焦油坑

编程行业为什么有趣,因为它不仅满足了我们内心深处进行创造的渴望,而且唤醒了每个人内心的情感,具体来说:

  1. 创建事物的快乐
  2. 开发对其它人有用东西的快乐
  3. 将零部件组装在一起,看到它们以精妙的方式运行,并收到了预期效果的乐趣
  4. 面对不重复的任务,持续学习的乐趣
  5. 工作在如此易于驾驭的介质上的乐趣,程序员几乎仅仅在单纯的思考中工作

当然,这个行业也有一些苦恼:

  1. 将做事方式调整到追求完美是学习编程最困难的部分
  2. 由其他人来设定目标,并且必须依靠自己无法控制的程序
  3. 编程过程中概念性设计是有趣的,但寻找琐碎的 bug 却往往枯燥烦闷
  4. 人们通常期望项目接近结束时,软件项目能收敛的快一些;然而情况是,越接近完成收敛得越慢
  5. 产品在完成前总面临着陈旧过时的威胁(设计被冻结)

这就是编程,一个许多人痛苦挣扎的焦油坑以及乐趣和苦恼共存的创造性活动。

第2章 人月神话

  1. 缺乏合理的进度安排是造成项目滞后的最主要原因,它比其它所有因素的总和影响还大
    • 我们对估算技术缺乏有效的研究,这隐含了假设:一切都将运作良好
    • 我们采用的估算技术隐含了假设人月可以互换,错误地将进度和工作量相互混淆
    • 我们对自己的估计技术缺乏信心,在管理和客户的压力下,我们常常缺乏坚持的勇气
    • 对进度缺少跟踪和监督
    • 当意识到进度的偏离时,下意识的反应是增加人力,反而使事情更糟
  2. 所有编程人员都是乐观主义者:一切都将运作良好
  3. 良好的烹饪需要时间,某些任务无法再不损害结果的情况下加快速度
  4. 用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话,它暗示着人员数量和时间是可以相互替换的
    • 人员数量和时间的互换仅适用于:某个任务可以分解给参与人员,并且他们之间不需要相互的交流
    • 在若干人员中分解任务会引发额外的沟通工作量:培训和相互沟通
  5. 向进度落后的项目中增加人手,只会使进度更加落后。因为它会带来这些成本:任务重新分配本身和所造成的工作中断;培训新人员;额外的相互沟通

第3章 外科手术队伍

  1. 需要协作的人员数量影响着开发成本,因为成本的主要组成部分是相互的沟通和交流,以及更正沟通不当所引起的不良结果(系统调试)
  2. 一拥而上的开发方法是高成本、速度缓慢、低效的,开发出的产品无法进行概念上的集成
  3. 一位首席程序员(架构师)、类似于外科手术队伍的团队架构提供了一种方法:既能获得由少数头脑产生的产品完整性,又能得到多位协助人员的总体生产率,还彻底减少了沟通的工作量

第4章 贵族专制、民主政治和系统设计

  1. 在系统设计中,概念完整性是最重要的考虑因素
  2. 将体系结构方面的工作与具体实现相分离是获得概念完整性的强有力方法
    • 设计必须由一个人或者具有共识的小型团队来完成
    • 体系结构陈述的是发生了什么,而实现描述的是如何实现
  3. 如果要得到系统概念上的完整性,就必须有人控制这些概念,这实际上是一种无需任何歉意的贵族专制统治
  4. 体系结构、设计实现、物理实现的许多工作可以并行
  5. 具体实现和体系设计是性质不同的创造工作,产品的成本性能比在很大程度上依靠实现人员,而易用性很大程度上依赖架构师
  6. 纪律规则对行业是有益的,外部的体系结构规定实际上是增强而不是限制实现小组的创造性

第5章 画蛇添足

  1. 尽早的交流和沟通能使架构师有较好的成本意识,使开发人员获得对设计的信心,并且不会混淆各自的责任分工
  2. 架构师如何成功的影响实现:
    • 牢记是开发人员承担创造性的实现责任,架构师只能建议而不能支配
    • 时刻准备为所指定的说明建议一种实现的方法,同样准备接受其他任何可行方法
    • 对上述的建议保持低调和不公开
    • 准备放弃坚持所作的改进建议
    • 听取开发人员在体系结构上的改进建议
  3. 第二个系统是人们所设计的最危险的系统,它通常会被过分设计

第6章 贯彻执行

  1. 即使是大型的设计团队,设计也必须由一个或两个人来完成,以确保这些决定是一致的
  2. 出于精确性的考虑,我们需要形式化地设计定义;同样,我们需要记叙性定义来加深理解
  3. 允许架构师对实现人员的询问做出解释是非常重要的,并且必须进行日志记录和整理发布
  4. 项目经理最好的朋友是他每天要面对的对手:独立的产品测试小组

第7章 为什么巴比伦塔会失败

  1. 巴比伦塔项目的失败是因为缺乏交流以及交流的结果:组织
  2. 交流的缺乏导致了争辩、沮丧和群体猜忌,很快,团队开始分裂,大家选择了孤立,而不是相互争吵
  3. 团队应该尽可能多的方式进行相互之间的交流
    • 非正式地进行简要技术陈述的常规项目会议
    • 共享的正式项目工作手册
  4. 项目工作手册不是独立的一篇文档,它是对项目必须产生的一系列文档进行组织的一种结构
    • 必须尽早和仔细的设计工作手册结构
    • 项目所有文档都必须是工作手册的一部分
    • 每一个团队成员都应该了解工作手册
    • 实时更新
  5. 每个子项目具有两个领导角色:产品负责人和架构师(技术主管),这两个角色的职能有很大区别需要不同的技能,如下组合是非常有效的
    • 两者是同一人:这种情况很少见,同时满足这两种角色的人才凤毛麟角
    • 产品负责人是总指挥,技术主管充当左右手
      • 产品负责人必须预先声明技术主管的技术权威
      • 在主要的技术问题出现之前,先私下讨论这些问题:产品负责人必须对技术主管的技术才能表现出尊重
      • 好处在于:项目经理可以使用并不擅长管理的技术天才来完成工作
      • 更适合大型项目
    • 技术主管是总指挥,产品负责人是左右手
      • 更适合小型项目

第8章 胸有成竹

  1. 仅仅对编码部分时间的估计,然后乘以其他部分的相对系数,是无法得到对整项工作的精确估计的
  2. 当使用适当的高级语言时,程序编写的生产率可以提高5倍

第9章 削足适履

  1. 大型团队中,各小组倾向于不断地局部优化,以满足自己的目标,而较少考虑对用户的整体影响。这种方向性问题是大型项目的主要危险
  2. 从系统整体出发以及面向用户的态度是软件编程管理人员最重要的职能
  3. 精炼、充分和快速的程序往往是战略性突破的结果,而不仅仅是技巧性的提高
    • 这种战略上的突破常常来自于对数据或表的重新表达。数据的表现形式是编程的根本

第10章 提纲挈领

  1. 对于软件项目,关键文档类似于:目标、用户手册、内部文档、进度、预算、组织架构图和工作空间分配
  2. 项目经理的基本职责是使每个人都向着相同的方向前进
  3. 项目经理的主要日常工作是沟通,而不是做出决定;文档使各项计划和决策在整个团队范围内得到交流

第11章 未雨绸缪

  1. 唯一不变的是变化,软件工程领域更是如此
  2. 开发人员交付的是用户满意度,而不仅仅是实际的产品
  3. 软件产品易于掌握的特性和不可见性,导致它的构建人员特别容易面临着永恒的需求变更
    • 用户的实际需要和用户感觉会随着程序的构建、测试和使用而变化
  4. 程序员不愿意为设计书写文档,不仅仅是因为惰性,更多的是源于他们的踌躇:要为自己尝试性的设计决策进行辩解
  5. 程序维护主要由各种变更组成:修复设计缺陷,新增功能,或使用环境或配置变换引起的调整
    • 缺陷修复总会以固定(20%~50%)的几率引入新的 bug ,整个过程是前进两步,后退一步
    • 维护成本受用户数目影响,用户越多,所发现的错误也越多
  6. 系统熵随时间增加:所有修改都倾向于破坏系统的架构,增加了系统的混乱程度(熵)

第12章 干将莫邪

  1. 巧匠因为他的工具而出名
  2. 项目经理应该制定一套策略,并为通用工具的开发分配资源
  3. 调试时系统编程中较慢和较困难的部分,而漫长的调试周转时间是调试的祸根
  4. 自上而下,彻底地开发一个性能仿真装置

第13章 整体部分

  1. 好的自上而下的设计从四个方面避免了 bug
    • 清晰的结构和表达方式更容易对需求和模块功能进行精确地描述
    • 模块分割和模块独立性避免了系统级的 bug
    • 细节的控制使结构上的缺陷更加容易识别
    • 设计在每个步骤上是可以测试的,测试可以尽早开始
  2. 系统调试(相对于单元测试)所花费的时间会比预料的更长

第14章 祸起萧墙

  1. 一天一天的进度落后比起重大灾难更难以识别,更不容易防范和更加难以弥补
  2. 里程碑必须是具体、特定和可度量的事件,能进行清晰的定义
  3. 状态的获取是困难的,因为下属经理有充分的理由不提供信息共享
    • 减少角色冲突和鼓励状态共享
    • 猛地拉开地毯
  4. 对计划和控制职能进行适度的技术人力投资是非常值得赞赏的

第15章 另外一面

  1. 尽可能的写文档,因为记忆并不可靠
  2. 使用自文档技术写文档,文档除了描述事情如何,还应阐述它为什么那样

第16章 没有银弹

  1. 所有软件活动包括
    • 必要任务:打造抽象软件实体的复杂概念结构
    • 次要任务:用编程表达这些抽象实体,在空间和时间的限制下映射成机器语言
  2. 没有任何技术或管理上的进展,能够独立地许诺在生产率、可靠性或简洁性上取得数量级的提高
  3. 软件系统中无法规避的内在特性:复杂度、一致性、可变性和不可见性
  4. 解决次要问题的一些突破:高级语言,分时,统一编程环境
  5. 银弹的希望?高级语言,面向对象编程,专家系统,自动编程,图形化编程,程序验证,环境和工具,工作站
  6. 针对概念上根本问题的有前途的方法
    • 进行市场调研,避免开发已上市产品,使用购买和二次开发
    • 快速原型开发
    • 有机地更新软件
    • 挑选和培养卓越概念设计人员

第17章 再论“没有银弹”

  1. 如果开发的次要任务少于整个工作的9/10,即使不占用任何实现,也不会给生产率带来数量级的提高,所以必须解决开发的根本问题
  2. 可重用和可交互的构件开发是解决软件根本困难的一种方法

第18章 《人月神话》的观点:是与非

本章内容实际上是前面所有章的总结和摘要,这里不再重复。

第19章 20年后的人月神话

  1. 人月神话是关于人和团队的书,它的淘汰过程会是缓慢的
  2. 概念完整性是产品质量的核心,拥有一位架构师是迈向概念完整性最重要的一步
    • 将体系结构和设计实现、物理实现相分离
    • 架构师方案的重用
  3. 增量开发模型更佳:渐进地精化
  4. 信息隐藏是面向对象编程中唯一提高软件设计水平的途径

附录

  1. 有些书对于读者和作者就像年金,它们年复一年地分红,比如《人月神话》
  2. 项目计划可以从以下方面考虑:项目描述、项目组织架构、软件生命周期、项目管理、配置管理
Comments
Write a Comment