整理了书中55个事实和10个谬论。可能由于书写时间是十多年前(2002出版英文版),所以对部分表示赞同,部分持反对态度。其中的讨论和争议都是书中的观点整理,沉思是自己的思考。

55个事实

管理

人员

  1. 在软件开发中,最重要的因素不是程序员采用的工具和技术,而是程序员自身的质量。
    • 讨论:
      • 提倡过程,工具和技术 -> 凌驾于人员之上
      • 人员是可随意更换的螺丝钉,时间表 + 严格限制 = 工作出色 -> 不信任程序员,要求他们信任我们
      • CMM(能力成熟度模型):良好的过程会得出良好的软件 -> P-CMM(个人能力成熟度模型):持续提高组织整体人力资源能力
    • 争议:
      • 表面承认,行为否认。
      • 技术人员希望通过新技术来简化工作
  2. 对“个体差异”的研究表明,最好的程序员要比最差的程序员强28倍之多。即使他们的报酬不同,优秀程序员也是软件业中最廉价的劳动力。
    • 讨论:
      • 实际上比别人强28倍的人所得的报酬还不及别人的2倍
    • 争议:
      • 没人怀疑正确性,但是忽略其重要性。
  3. 给延期的项目增加人手会使项目进一步延期
    • 讨论:
      • 加人 = 培训 + 消耗现有人的时间精力 + 贡献慢 + 人数增多带来的交流复杂 = 项目进一步延期
    • 争议:
      • 事实正确,细节争议。
      • 新人熟悉当前领域,学习过程缩短;项目刚开始加入,新人提速更容易。
      • 以上事实只在易于确定和避免的特定环境中才有效
      • 为了提速而加人应该慎重
  4. 工作环境对工作效率和产品质量具有深刻影响
    • 讨论:
      • 软件是智力密集型的,构建软件的环境应该有利于思考。
      • 空间宽敞,安静,尊重隐私,少不必要的干扰 -> 提高效率
    • 争议:
      • 额外空间需要资金容易衡量,因为拥挤对效率的影响无法衡量
      • 可以严格度量的东西可以从不能度量的东西那里转移人的注意力
      • 结对编程

工具和技术

  1. 夸大宣传是软件的瘟疫。多数软件工具对于效率和质量的提高幅度仅为5%~35%。但是总有人反复说提高幅度是“数量级”的。
    • 讨论:
      • 在很久以前,的确有能够形成突破性的技术,而现在则日益减少
      • 现在很多技术或者思想上的突破,对构建软件的能力并没有显著的帮助
      • 宣传 - 期望破灭的怪圈
    • 争议:
      • 计算机领域的核心文化之一就是新事物优于旧事物
  2. 在学习新工具或者新技术的初期,程序员的工作效率和产品质量都会下降。只有克服了学习曲线之后,才可能得到实质性的收益。只有满足下面两个条件,采用新工具或新技术才有意义:(a)新东西确实有用;(b)要想获得真正的收益,必须耐心等待。
    • 讨论:
      • 采用新思想的第一个项目会比以往的项目更慢,而不是更快
      • 学习曲线,刚开始效率和效力下降,然后超过原有水平,然后稳定在该技术应有的水平
      • 学习曲线的长度因形势和环境而异,最终受益越大,曲线越长。无法确定曲线的时间长短。
      • 通过询问有经验的人,来获得教训和经验(不要询问狂热者,他们给出的是信念的答案)
    • 争议:
      • 不应该有争议
      • 狂热者通常要求新方法一引入就步入正轨,他们总是设想一开始就能得到收益
  3. 软件开发者对于工具说的多,评估的少,买的多,用的少。
    • 讨论:
      • 开发者热衷于尝试新工具,但是很少使用。
      • 新工具在生效前是个负担,开发者习惯用惯用的工具来开发软件。
    • 争议:
      • 程序员会在可以保证更快完成工作的前提下选择新事物,假如前提无法满足(学习曲线),则又会使用旧的可靠的事物
      • 我们采用不切实际的时间表,而且按其行事,这是过于重视时间表而无暇学习新观念的文化观念

估算

  1. 项目失控的两个最主要的原因之一是糟糕的估算
    • 讨论:
      • 失控项目:无任何成果或有成果,但是滞后于时间表、超出预算
      • 通常是太乐观的估算,我们的估算通常是主观愿望,而不是客观目标
  2. 许多估算是在软件生命周期开始时完成的。后来,我们才认识到在需求定义之前,即理解问题之前进行项目估算是不正确的;也就是说,估算时机是错误的。
    • 讨论:
      • 有意义的估算 = 项目有一定的了解 = 确定需求 = 确定需要解决的问题
  3. 许多软件项目都是由高层管理人员或者营销人员来估算,而不是由真正构建软件的人或者他们的主管来进行评估的。因此,估算软件的人员是错误的。
    • 讨论:
      • 常识:估算软件应该是了解软件的人;事实:估算软件是需要软件产品的人。
      • 主观期望 > 客观真实
    • 争议:
      • 明白软件和不明白软件的人之间存在隔阂;
      • 软件人员知道什么是不可能,管理人员不听取警告;导致两边人互相不信任。
  4. 软件估计很少根据项目进度进行调整。因此,这些估算通常是错误的人在错误的时间得出的错误结果。
    • 讨论:
      • 软件人员对于错误的估算逆来顺受
      • 管理人员不乐意调整原来的估算
  5. 因为估算的数据如此糟糕,所以在软件项目不能达到估算目标时,不应该再考虑估算。但是无论如何,每个人都在考虑它。
    • 讨论:
      • 时间表并非唯一的管理方法(根据解决问题数量,克服风向指标,工作量等来管理)
  6. 在管理者和程序员之间存在隔阂。对于一个未满足估算目标的项目的调查表明:从管理者看来这是一个失败的项目,而在技术人员看来确实成功的项目。
    • 讨论:
      • 技术人员比管理人员早意识到软件失控,但一般不会报告给管理者
      • 项目进展速度:不做估算 > 技术人员做估算 > 管理人员做估算
    • 争议:
      • 什么是项目成功的组成要素,程序员应该和管理人员达成一致
  7. 对于可行性调研的回答几乎总是“可行”。
    • 讨论:
      • 乐观主义
      • 我们很少在开始之前真正做可行性研究

复用

  1. 小规模的复用(子程序库)开始于50多年前,这个问题已经得到很好的解决。
    • 讨论:
      • 小规模复用成功之后,大规模复用方面虽然投入了大量的精力,但是多年来并没有获得明显的改变。
  2. 虽然每个人都认为大规模复用(组件)非常重要、非常急需,但是这个问题至今还没有基本解决。
    • 讨论:
      • 构建大规模的可复用组件完全和小规模的可复用组件完全不是一回事
      • 软件的多样性
  3. 大规模复用最好适用于相关的系统,也就是依赖于具体应用领域,这样就限制了它的应用范围。
    • 讨论:
      • 不可能建立适用于多个应用领域的组件,但是建立某个领域内的组件却容易的多
  4. 有关复用问题,有两个“三倍法则”:(a)构建可复用的组件比使用组件难三倍;(b)在将组件收录到复用库并成为通用组件之前,应该在三个不同的应用中尝试该组件。
  5. 修改复用的代码特别容易引起错误。如果一个组件中超过20%~25%的代码需要修改,那么重新实现的效率会更高。
  6. 设计模式复用是解决代码复用中固有问题的一种方法。

复杂性

  1. 问题的复杂性每增加25%,解决方案的复杂性就增加100%。这不是一个可改变的条件(即使人们都努力降低复杂性),而是客观存在的。
  2. 80%的软件工作是智力活动。相当大的比例是创造性的活动。很少是文书性的工作。

生命周期

需求

  1. 导致项目失控的两个最常见原因之一是不稳定的需求
  2. 在产品完成时修订需求错误的代价最大,在开发早起修订需求错误的代价最小。
  3. 遗漏需求是最难修订的需求错误。

设计

  1. 从需求转入设计时,因为制定方案过程的复杂性,会激增出大量的衍生需求(针对一种特定设计方案的需求),设计需求是原始需求的50倍之多。
  2. 对于一个软件问题,通常不存在唯一的最佳设计方案。
  3. 设计是一个复杂的、迭代的过程。最初的设计方案可能是错误的,当然也不是最优的。

编码

  1. 从设计转到编码阶段时,设计者按照自己掌握的水平,已经将问题分解为“原语”。如果编程者和设计者不是同一个人,二者的“原语”不吻合,就会出问题。
  2. COBOL是一种非常糟糕的语言,但是其他的(用于商业数据处理的)语言也同样糟糕。

错误消除

  1. 错误消除是软件生命周期中最耗时的阶段。

测试

  1. 普通程序员认为已经彻底测试过的软件其实只执行了55%~60%的逻辑路径。采用覆盖分析器等自动工具,可以将上述比例提高到85%~90%。几乎不可能测试软件中100%的逻辑路径。
  2. 即使测试覆盖有可能达到100%,这种测试也不够。大于35%的错误是源于逻辑路径的确实,还有40%的错误源于执行特定的路径组合。不可能实现100%的覆盖。
  3. 没有工具就无法做好错误消除工作。人们常用调试器,很少使用覆盖分析器等其他工具。
  4. 自动测试很少,也就是说有些测试可以也应该自动化,但是有许多测试任务不能自动完成。
  5. 程序员在程序中嵌入测试代码、目标代码中的编译参数等方式,都是测试工具的重要补充。

点评和检查

  1. 在运行第一个测试用例之前进行严格审查可以消除软件产品中多大90%的错误。
  2. 虽然严格审查有很多优先,但是不能也不应该代替测试。
  3. 通常认为,事后评审对于了解客户的满意度和改进过程都很重要。但是很多软件公司不开展时候评审。
  4. 同行评审设计技术和社会两方面问题,忽视任何一方面都会产生严重的灾难。

维护

  1. 维护开支通常占软件成本的40%~80%(平均为60%)。因此,维护可能是软件生命周期中最重要的阶段。
  2. 增强功能大约占软件维护成本的60%,错误更正仅占17%。因此,软件维护的主体是在旧软件中加入新功能,而不是更正错误。
  3. 维护是解决方案,而不是问题。
  4. 比较软件开发和软件维护中的工作,除了维护中“理解现有的产品”这项工作外,其他工作都一样。这项工作占据了大约30%的维护时间,是主要的维护活动。因此可以说维护比开发更难。
  5. 更好的软件工程开发导致更多而不是更少的维护。

质量

质量

  1. 质量是一组属性的集合
  2. 软件质量不是用户满意、满足需求、满足成本和时间表目标,或者可靠性。

可靠性

  1. 绝大多数程序员都会犯某些错误。
  2. 错误通常聚集在一起。
  3. 没有唯一最好的消除软件错误的方法。
  4. 总会有残存的错误。我们的目标应该是消除严重错误,或者使之最少。

效率

  1. 效率主要来自于优秀的设计,而不是优秀的编码。
  2. 高级语言代码配合摄当的编译器优化,大约可以达到汇编语言90%的效率。对于一些复杂的现代体系结构,效率更高。
  3. 在空间和时间之间存在折衷。通常,改进一方面会降低另外一方面。

研究

  1. 许多软件研究者不是做调查,而是鼓吹,因此,(a)有些概念比鼓吹的糟糕、更少;(b)缺少有助于确定这些概念真实价值的评估性研究。

5+5谬论

管理

  1. 你不能管理自己无法度量的东西
  2. 可以管理软件产品的质量

人员

  1. 可以,也应该“忘我”地编程

工具和技术

  1. 工具和技术是通用的
  2. 软件需要更多的方法论

估算

  1. 要估算成本和时间表,应首先估算代码行数

生命周期

测试

  1. 随机测试输入是优化测试的好方法

评审

  1. ”假如有了足够多的关注,所有的bug都显而易见。”
    • 讨论:
      • 错误的深浅与查找错误的人数没有关系

维护

  1. 估计将来的维护成本和做出产品更新的决策需要参考过去的成本数据。
    • 讨论:
      • 软件维护主要是功能增强,而功能增强的频率没有规律。

教育

  1. 教别人编程的方法是教别人写程序
    • 讨论:
      • 学习编程应该是先读后写,而现在都是先写后读
      • 为什么会出现该情况:
        • 教授读代码需要挑选范例,无法找到一些很好的示范代码。
        • 没有指导读代码的教科书,都是教授写代码的。
        • 已形成了先写后读的制度,很难改变。
    • 争议:
      • 没有争议,但是没人来改变现状。
    • 沉思:
      • 教授写代码的书,也会有部分的代码示例,我们学习的时候也是看懂了示例代码,然后去敲一下示例代码,或者在示例代码的基础上做简单的改动,应该也可以算是先读后写。那作者这个先读的定义是?比如阅读一些经典的项目代码?