1.2 软件工程取得了哪些进展
软件工程(第4版•修订版)
编写软件既是一门艺术也是一门科学。作为一名计算机专业的学生,深入理解这句话是非常重要的。计算机科学家和软件工程研究人员研究的是计算机的机制,并建立起使它们具有更高生产率、更有效的理论。但同时,他们也设计计算机系统并编写程序,执行相关任务,这是一项融合艺术、天赋和技巧的实践性工作。在具体的系统上执行特定任务,可能会存在很多方法,但是,某一种方法可能更有效、更精确、更易于修改、更容易使用或更便于理解。任何黑客都能够编写代码完成工作,但是,要写出健壮的、易于理解和维护的并且能以最高效的方式完成工作的代码,必须具备专业软件工程师的技巧和洞察力。因此,软件工程的目标就是设计和开发高质量软件。
在学习生产高质量软件系统所需要的知识之前,先回头了解一下我们取得了哪些成就。考虑这样一个问题:用户是否对现有软件系统感到满意?答案可能是“满意”,也可能是“不满意”。一方面,软件使我们比以往任何时候都能够更快、更有效地完成任务。例如,想一下,在字处理、表格处理、电子邮件或网络电话等现代化技术出现之前,人们的生活是怎样的呢?软件支撑着医学在生命维持治疗或生命救治方面的进展,以及农业、交通和其他诸多产业取得进展;另外,软件已经使我们能够做到以前从来不敢想象的事情,如显微外科手术、多媒体教育、机器人等。
但是,软件也不是完美无缺的,系统的功能通常并不完全符合用户的期望。我们都听说过系统几乎不能运行这样的事情。我们所有人都编写过有故障的程序:代码包含错误,但也刚好可用或足以证明一个方法的可行性。显然,如果开发出这样的系统交付给客户,客户是不能接受的。
课程项目中的错误和大型软件系统中的错误不可同日而语。事实上,软件故障和生产无故障软件的困难性是文献和闲谈中经常讨论的问题。有些故障仅仅是令人讨厌,而有一些故障则会耗费大量的时间和金钱,甚至还有一些可能会危及生命。补充材料1-1解释了故障、错误和失效之间的关系。我们在此讨论几个关于故障的例子,看一看问题出在哪里以及其中的原因是什么。
补充材料1-1 描述“bug”的术语
我们常常会谈到软件中的“bug”,根据不同的上下文,它有多种含义。“bug”既可以指解释需求时犯的错误,也可以指一段代码中的语法错误,还可以指由于未知因素引起系统崩溃的原因。IEEE有描述软件产品(IEEE 1983)中“bug”的标准术语(见IEEE标准729)。
当人们在进行软件开发活动的过程中出错时(称为错误(error)),就会出现故障(fault)。例如,设计人员可能误解了某个需求,创建出与需求分析人员和用户的实际意图不相符的设计。这个设计故障是一种错误的编码,可能导致其他故障,如不正确的代码或用户手册中不正确的描述等。因此,单个错误可能产生多个故障,并且故障可能驻留在任何开发或维护的产品中。
失效(failure)是指系统违背了它应有的行为。它可能会在系统交付前或交付后被发现,也可能在测试过程中或者在运行和维护的过程中被发现。我们在第4章会看到,需求文档可能会包含故障,所以即使系统按照需求规格说明来运行,如果它未进行应有的行为,也称为失效。
因此,故障是系统的内部视图,这是从开发人员的角度看待系统;而失效是系统的外部视图,它是用户所看到的问题。并非每一个故障都对应于一个失效,例如,如果不执行故障代码,或者不进入某个特定状态,那么故障就不会使代码失效。图1-4所示说明了失效的起源。
20世纪80年代早期,美国国家税务局(Internal Revenue Service,IRS)雇佣Sperry公司构建一个联邦收入所得税表格自动处理系统。根据《华盛顿邮报》的报道,“系统……被证明难以承载当前的工作负荷,成本几乎是预算的两倍,必须尽快更换”(Sawyer 1985)。在1985年,还需花费额外的9千万美元来升级Sperry公司最初价值1.03亿美元的设备。另外,因为出现的问题妨碍了IRS在最后期限前及时向纳税人退税,IRS被迫向纳税人支付4020万美元的利息,并且要向自己的员工支付2230万美元的加班工资。到1996年的时候,情况仍未改善。《洛杉矶时报》在3月29日报道:除了6000页的技术文档外,目前系统的升级仍未有整体规划。国会议员Jim Lightfoot把这个项目称为“因为规划失当而正在挣扎的40亿美元的惨败”(Vartabedian 1996)。
诸如此类的情况仍然时有发生。在美国,联邦调查局(FBI)的“三部曲”(Trilogy)项目尝试着更新FBI的计算机系统。但其结果却是毁灭性的:“经历了四年多的艰苦工作,花费了5亿美元,但是,据报道:‘三部曲’项目几乎没有改善陈旧的案例管理系统,迄今为止,该系统仍然混乱不堪,深陷于带有绿色屏幕的大型机和大量的纸介档案之中。”(Knorr 2005)。类似地,在英国,对“国家保健服务”信息系统的大修,耗费了两倍的预算(Ballard 2006)。第2章将讨论为什么项目计划对于生产高质量的软件产品是至关重要的。
多年来,公众在日常生活中不断被灌输:软件不存在问题。但里根总统提出的主动战略防御(Strategic Defense Initiative,SDI)增强了公众对开发无故障软件系统的困难性的认识。报纸和杂志上一些有影响的报道(比如Jacky 1985, Parnas 1985, Rensburger 1985)描述了计算机科学界中的怀疑论的观点。20年后,当美国国会被要求拨款来建立一个类似系统的时侯,许多计算机科学家和软件工程师仍然认为,在编写和测试软件时,没有办法确保它具备充分的可靠性。
例如,许多软件工程师认为反弹道导弹系统至少需要1千万行代码,有些人甚至估计其代码量会高达1亿行。相比较而言,支持美国航天飞机的软件只包含300万行代码,包括控制发射和飞行的地面控制计算机所用的程序。1985年,航天飞机上只有10万行代码(Rensburger 1985)。因此,反导弹软件系统将需要海量的代码测试。再者,可靠性约束是无法测试的。要了解其中的原因,考虑安全攸关(safety-critical)软件的概念。通常我们说某些事情是安全攸关的(即这些事情的失败会对生命或健康构成威胁),则其可靠性至少应当是109。正如我们将在第9章中看到的那样,这意味着系统在109小时的运行期间其失效不能超过一次。要观察可靠性的程度,这个系统应运行至少109小时来验证它不会失效,但是109小时是114 000多年——作为一个测试时间段来说,它实在是太长了!
我们在第9章中还将看到,当软件设计有误或编程有误的时候,原本有用的技术可能会变成致命的。例如,当Therac-25(一种射线疗法和X光设备)发生故障并致使几个病人死亡的时候,医学界变得惊恐万状。软件设计人员没有预料到会有不按操作规范使用几个方向键的情况。其结果是,当需要低剂量的射线束时,软件却保持高剂量的设置并发出了极为集中的射线束(Leveson and Turner 1993)。
很容易找到类似的意想不到的使用方式的例子。例如,最近使用一些商业现货构件(作为节省开支的手段,而不是对软件的定制加工)导致以一种原先设计者未曾设想的方式使用这些构件的设计。许多许可协议明确地指出这种意想不到的使用方式所带来的风险:“因为每一个终端用户系统都是定制的,并且与该软件所使用的测试平台不同;还因为用户或应用设计人员将其他产品结合在一起,以厂商或供应商未曾评估或未曾考虑过的方式使用该软件,因此,用户或应用设计人员最终对该软件的验证和确认负责。”(Lookout Direct,未注明出版日期。)
在整个软件设计活动的过程中,必须考虑对系统意想不到的使用方式。至少可以用两种方式来处理这些非正常的使用:一是通过你的想象来考虑系统可能如何被滥用(以及正确使用),二是假定系统将被滥用并设计软件来处理这种滥用。我们将在第8章讨论这些方法。
尽管许多厂商努力设计零缺陷的软件,但事实上,大多数软件产品都不是无故障的。市场压力促使软件开发人员快速交付产品,几乎没有时间进行完全的测试。通常,测试小组只能测试那些最有可能用到的功能,或那些最有可能危及用户或激怒用户的功能。基于这样的原因,许多用户在安装系统的第一个版本时都很谨慎。他们知道,直到第二个版本,这些“bug”才会得到解决。此外,对已知故障进行修复有时是非常困难的,甚至重写整个系统都要比改变现有代码更加容易。我们将在第11章中探讨软件维护过程中所涉及的问题。
尽管在现实生活中,有些软件取得了巨大成功并被全面接受,但是,我们生产的软件的质量仍然有很大的改进余地。例如,缺乏质量的代价是高昂的,一个故障未被检测到的时间越长,改正它的花费就越大。尤其是,在项目最初的分析阶段改正一个错误,比起把系统移交给客户后再去改正,所需成本只有后者的1/10。不幸的是,我们没有在早期捕捉到大多数的错误。改正在测试和维护过程中发现的故障的一半成本,是来自于系统生命周期的更早阶段所犯的错误。在第12章和第13章中,我们将讨论评估开发活动有效性的方法,以及对过程加以改进以尽可能早地捕捉到错误的方法。
我们提出的一种简单而有效的技术是使用评审和审查。许多学生习惯于自己开发和测试软件,但是他们的测试并没有他们想象的那么有效。例如,Fagan研究了故障的检测方法。他发现,采用以测试数据运行程序的方法只能找出开发阶段故障的1/5。然而,同行评审(由同事检查和评论彼此的设计和代码的过程)能够揭示出其余4/5的故障(Fagan 1986)。因此,请你的同事来评审你的工作,软件质量会有大幅度的提高。在后面的章节中,我们将学习如何在每个主要开发步骤之后,利用评审和审查的过程尽可能早地发现并修复故障。并且,我们将在第13章了解到如何改进审查过程。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。