热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

没有银弹-软件工程中的根本和次要问题

没有任何技术或管理上的进展,能够独立地许诺十年内使生产率、可靠性或简洁性获得数量级上的进步。Thereisnosingledevelopment,ine

没有任何技术或管理上的进展,能够独立地许诺十年内使生产率、可靠性或简洁性获得数量 级上的进步。

There is no single development, in either technology or management technique, which by itself promises even one order-of-magnitude improvement within a decade in productivity, in reliability, in simplicity.

摘要1

所有软件活动包括根本任务——打造由抽象软件实体构成的复杂概念结构,次要任务 ——使用编程语言表达这些抽象实体,在空间和时间限制内将它们映射成机器语言。软件生 产率在近年内取得的巨大进步来自对后天障碍的突破,例如硬件的限制、笨拙的编程语言、 机器时间的缺乏等等。这些障碍使次要任务实施起来异常艰难,相对必要任务而言,软件工 程师在次要任务上花费了多少时间和精力?除非它占了所有工作的 9/10,否则即使全部次 要任务的时间缩减到零,也不会给生产率带来数量级上的提高。

因此,现在是关注软件任务中的必要活动的时候了,也就是那些和构造异常复杂的抽 象概念结构有关的部分。我建议:

仔细地进行市场调研,避免开发已上市的产品。
在获取和制订软件需求时,将快速原型开发作为迭代计划的一部分。
有机地更新软件,随着系统的运行、使用和测试,逐渐添加越来越多的功能。

不断挑选和培养杰出的概念设计人员。
- 102 -

介绍

在所有恐怖民间传说的妖怪中,最可怕的是人狼,因为它们可以完全出乎意料地从熟 悉的面孔变成可怕的怪物。为了对付人狼,我们在寻找可以消灭它们的银弹。

大家熟悉的软件项目具有一些人狼的特性(至少在非技术经理看来),常常看似简单明 了的东西,却有可能变成一个落后进度、超出预算、存在大量缺陷的怪物。因此,我们听到 了近乎绝望的寻求银弹的呼唤,寻求一种可以使软件成本像计算机硬件成本一样降低的尚方 宝剑。

但是,我们看看近十年来的情况,没有银弹的踪迹。没有任何技术或管理上的进展, 能够独立地许诺在生产率、可靠性或简洁性上取得数量级的提高。本章中,我们试图通过分 析软件问题的本质和很多候选银弹的特征,来探索其原因。

不过,怀疑论者并不是悲观主义者。尽管我们没有看见令人惊异的突破,并认为这种 银弹实际上是与软件的内在特性相悖,不过还是出现了一些令人振奋的革新。这些方法的规 范化、持续地开拓、发展和传播确实是可以在将来使生产率产生数量级上的提高。虽然没有 通天大道,但是路就在脚下。

解决管理灾难的第一步是将大块的“巨无霸理论”替换成“微生物理论”,它的每一步 ——希望的诞生,本身就是对一蹴而就型解决方案的冲击。它告诉工作者进步是逐步取得的, 伴随着辛勤的劳动,对规范化过程应进行持续不懈的努力。由此,诞生了现在的软件工程。

是否一定那么困难呢?——根本困难

不仅仅是在目力所及的范围内,没有发现银弹,而且软件的特性本身也导致了不大可 能有任何的发明创新——能够像计算机硬件工业中的微电子器件、晶体管、大规模集成一样 ——提高软件的生产率、可靠性和简洁程度。我们甚至不能期望每两年有一倍的增长。

首先,我们必须看到这样的畸形并不是由于软件发展得太慢,而是因为计算机硬件发 展得太快。从人类文明开始,没有任何其他产业技术的性价比,能在 30 年之内取得 6 个数 量级的提高,也没有任何一个产业可以在性能提高或者降低成本方面取得如此的进步。这些

- 103 -

进步来自计算机制造产业的转变,从装配工业转变成流水线工业。

其次,让我们通过观察预期的软件技术产业发展速度,来了解中间的困难。效仿亚里 士多德,我将它们分成根本的——软件特性中固有的困难,次要的——出现在目前生产上的, 但并非那些与生俱来的困难。

  我们在下一章中讨论次要问题。首先,来关注内在、必要的问题。

一个相互牵制关联的概念结构,是软件实体必不可少的部分,它包括:数据集合、数 据条目之间的关系、算法、功能调用等等。这些要素本身是抽象的,体现在相同的概念构架 中,可以存在不同的表现形式。尽管如此,它仍然是内容丰富和高度精确的。

我认为软件开发中困难的部分是规格化、设计和测试这些概念上的结构,而不是对概 念进行表达和对实现逼真程度进行验证。当然,我们还是会犯一些语法错误,但是和绝大多 数系统中的概念错误相比,它们是微不足道的。

  如果这是事实,那么软件开发总是非常困难的。天生就没有银弹。

让我们来考虑现代软件系统中这些无法规避的内在特性:复杂度、一致性、可变性和 不可见性。

复杂度。规模上,软件实体可能比任何由人类创造的其他实体要复杂,因为没有任何 两个软件部分是相同的(至少是在语句的级别)。如果有相同的情况,我们会把它们合并成 供调用的子函数。在这个方面,软件系统与计算机、建筑或者汽车大不相同,后者往往存在 着大量重复的部分。

数字计算机本身就比人类建造的大多数东西复杂。计算机拥有大量的状态,这使得构 思、描述和测试都非常困难。软件系统的状态又比计算机系统状态多若干个数量级。

同样,软件实体的扩展也不仅仅是相同元素重复添加,而必须是不同元素实体的添加。 大多数情况下,这些元素以非线性递增的方式交互,因此整个软件的复杂度以更大的非线性 级数增长。

软件的复杂度是必要属性,不是次要因素。因此,抽掉复杂度的软件实体描述常常也 去掉了一些本质属性。数学和物理学在过去三个世纪取得了巨大的进步,数学家和物理学家 们建立模型以简化复杂的现象,从模型中抽取出各种特性,并通过试验来验证这些特性。这

- 104 -

些方法之所以可行——是因为模型中忽略的复杂度不是被研究现象的必要属性。当复杂度是 本质特性时,这些方法就行不通了。

上述软件特有的复杂度问题造成了很多经典的软件产品开发问题。由于复杂度,团队 成员之间的沟通非常困难,导致了产品瑕疵、成本超支和进度延迟;由于复杂度,列举和理 解所有可能的状态十分困难,影响了产品的可靠性;由于函数的复杂度,函数调用变得困难, 导致程序难以使用;由于结构性复杂度,程序难以在不产生副作用的情况下用新函数扩充; 由于结构性复杂度,造成很多安全机制状态上的不可见性。

复杂度不仅仅导致技术上的困难,还引发了很多管理上的问题。它使全面理解问题变 得困难,从而妨碍了概念上的完整性;它使所有离散出口难以寻找和控制;它引起了大量学 习和理解上的负担,使开发慢慢演变成了一场灾难。

一致性。并不是只有软件工程师才面对复杂问题。物理学家甚至在非常“基础”的级 别上,面对异常复杂的事物。不过,物理学家坚信必定存在着某种通用原理,或者在夸克中, 或者在统一场论中。爱因斯坦曾不断地重申自然界一定存在着简化的解释,因为上帝不是专 横武断或反复无常的。

软件工程师却无法从类似的信念中获得安慰,他必须控制的很多复杂度是随心所欲、 毫无规则可言的,来自若干必须遵循的人为惯例和系统。它们随接口的不同而改变,随时间 的推移而变化,而且,这些变化不是必需的,仅仅由于它们是不同的人——而非上帝——设 计的结果。

某些情况下,因为是开发最新的软件,所以它必须遵循各种接口。另一些情况下,软 件的开发目标就是兼容性。在上述的所有情况中,很多复杂性来自保持与其他接口的一致, 对软件的任何再设计,都无法简化这些复杂特性。

可变性。软件实体经常会遭受到持续的变更压力。当然,建筑、汽车、计算机也是如 此。不过,工业制造的产品在出厂之后不会经常地发生修改,它们会被后续模型所取代,或 者必要更改会被整合到具有相同基本设计的后续产品系列。汽车的更改十分罕见,计算机的 现场调整时有发生。然而,它们和软件的现场修改比起来,都要少很多。

其中部分的原因是因为系统中的软件包含了很多功能,而功能是最容易感受变更压力 的部分。另外的原因是因为软件可以很容易地进行修改——它是纯粹思维活动的产物,可以

- 105 -

无限扩展。日常生活中,建筑有可能发生变化,但众所周知,建筑修改的成本很高,从而打 消了那些想提出修改的人的念头。

所有成功的软件都会发生变更。现实工作中,经常发生两种情况。当人们发现软件很 有用时,会在原有应用范围的边界,或者在超越边界的情况下使用软件。功能扩展的压力主 要来自那些喜欢基本功能,又对软件提出了很多新用法的用户们。

其次,软件一定是在某种计算机硬件平台上开发,成功软件的生命期通常比当初的计 算机硬件平台要长。即使不是更换计算机,则有可能是换新型号的磁盘、显示器或者打印机。 软件必须与各种新生事物保持一致。

简言之,软件产品扎根于文化的母体中,如各种应用、用户、自然及社会规律、计算 机硬件等等。后者持续不断地变化着,这些变化无情地强迫着软件随之变化。

不可见性。软件是不可见的和无法可视化的。例如,几何抽象是强大的工具。建筑平 面图能帮助建筑师和客户一起评估空间布局、进出的运输流量和各个角度的视觉效果。这样, 矛盾变得突出,忽略的地方变得明显。同样,机械制图、化学分子模型尽管是抽象模型,但 都起了相同的作用。总之,都可以通过几何抽象来捕获物理存在的几何特性。

软件的客观存在不具有空间的形体特征。因此,没有已有的表达方式,就像陆地海洋 有地图、硅片有膜片图、计算机有电路图一样。当我们试图用图形来描述软件结构时,我们 发现它不仅仅包含一个,而是很多相互关联、重叠在一起的图形。这些图形可能描绘控制流 程、数据流、依赖关系、时间序列、名字空间的相互关系等等。它们通常不是有较少层次的 扁平结构。实际上,在上述结构上建立概念控制的一种方法是强制将关联分割,直到可以层 次化一个或多个图形 2。

除去软件结构上的限制和简化方面的进展,软件仍然保持着无法可视化的固有特性, 从而剥夺了一些具有强大功能的概念工具的构造思路。这种缺憾不仅限制了个人的设计过 程,也严重地阻碍了相互之间的交流。 


推荐阅读
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 企业数据应用挑战及元数据管理的重要性
    本文主要介绍了企业在日常经营管理过程中面临的数据应用挑战,包括数据找不到、数据读不懂、数据不可信等问题。针对这些挑战,通过元数据管理可以实现数据的可见、可懂、可用,帮助业务快速获取所需数据。文章提出了“灵魂”三问——元数据是什么、有什么用、又该怎么管,强调了元数据管理在企业数据治理中的基础和前提作用。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • 无线认证设置故障排除方法及注意事项
    本文介绍了解决无线认证设置故障的方法和注意事项,包括检查无线路由器工作状态、关闭手机休眠状态下的网络设置、重启路由器、更改认证类型、恢复出厂设置和手机网络设置等。通过这些方法,可以解决无线认证设置可能出现的问题,确保无线网络正常连接和上网。同时,还提供了一些注意事项,以便用户在进行无线认证设置时能够正确操作。 ... [详细]
  • JavaScript设计模式之策略模式(Strategy Pattern)的优势及应用
    本文介绍了JavaScript设计模式之策略模式(Strategy Pattern)的定义和优势,策略模式可以避免代码中的多重判断条件,体现了开放-封闭原则。同时,策略模式的应用可以使系统的算法重复利用,避免复制粘贴。然而,策略模式也会增加策略类的数量,违反最少知识原则,需要了解各种策略类才能更好地应用于业务中。本文还以员工年终奖的计算为例,说明了策略模式的应用场景和实现方式。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文详细介绍了相机防抖的设置方法和使用技巧,包括索尼防抖设置、VR和Stabilizer档位的选择、机身菜单设置等。同时解释了相机防抖的原理,包括电子防抖和光学防抖的区别,以及它们对画质细节的影响。此外,还提到了一些运动相机的防抖方法,如大疆的Osmo Action的Rock Steady技术。通过本文,你将更好地理解相机防抖的重要性和使用技巧,提高拍摄体验。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
author-avatar
木易_迪迪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有