1968 年秋季,NATO(北大西洋公约组织,简称“北约”)的科技委员会召集了近 50 名一流的编程人员、计算机科学家和工业界巨头,讨论和制定摆脱软件危机的对策。在那次会议上第一次提出了“软件工程”这个概念。到现在,软件工程已有 50 多年的历程。
在这 50 多年的发展历程中,人们针对软件危机的表现和原因,经过不断的实践和总结,越来越认识到:按照工程化的原则和方法组织软件开发工作,是摆脱软件危机的一条主要出路。
下面介绍软件工程的定义和软件工程所包含的内容。
软件工程是一门研究如何用系统化、规范化、数理化等工程原则和方法进行软件的开发和维护的学科。它作为一门新兴的工程学科,主要研究软件生成的客观规律性,建立与系统化软件生成有关的概念、原则、方法、技术和工具,指导和支持软件系统的生产活动,以其达到降低软件生产成本、改进软件产品质量、提高软件生产率水平的目标。软件工程学从硬件工程和其他人类工程中吸收了许多成功的经验,明确提出了软件生命周期的模型,发展了许多软件开发与维护阶段适用的技术和方法,并应用于软件工程实践,取得了良好的效果。
软件工程的具体含义体现在以下 4 个方面:
①把软件开发看成一项有计划、分阶段、严格按照标准或规范进行的活动(软件工程是指导计算机软件开发和维护的工程学科,软件工程方法=工程方法+管理技术+技术方法)。
②将系统的、规范的、可度量的方法应用于软件的开发、运行和维护的过程(将工程化应用于软件中,并研究提到的上述途径)。
③要求采用适当的软件开发方法和支持环境及编程语言来表示和支持软件开发各阶段的各种活动,并使开发过程条令化、规范化,使软件产品标准化、开发人员专业化。
④用工程学的观点进行费用估算,制定进度,制定计划;用管理科学中的方法和原理进行软件生产的管理;用数学的方法建立软件开发中的各种模型和各种算法。
软件工程包括三个要素:方法、工具和过程。
软件工程方法为软件开发提供了如何做的技术。它包括多方面的任务,如项目计划与估算,软件系统需求分析,数据结构、系统总体结构的设计,具体算法的设计、编码、测试以及维护等。
软件工程工具为软件工程方法提供了自动的或半自动的软件支撑环境。目前,已经推出了许多软件工具,这些软件工具集成起来,称为计算机辅助软件工程(Computer Aided Software Engineering,CASE)的软件开发支撑系统。CASE将各种软件工具、开发机器和存放开发过程信息的工程数据库组合起来,形成软件工程环境。
软件工程过程则是将软件工程方法和软件工具综合起来以达到合理、及时地进行计算机软件开发的目的。过程定义了方法使用的顺序、要求交付的文档资料、为保证质量和协调变化所需要的管理及软件开发各个阶段完成的里程碑。
软件工程是一种层次化的技术。任何工程方法(包括软件工程)必须以有组织的质量保证为基础。全面的质量管理和类似的理念刺激了不断的过程改进,正是这种改进导致更加成熟的软件工程方法的不断出现。支持软件工程的根基就在于对质量的关注。
软件开发模型(Software Development Model)是指软件开发全部过程、活动和任务的结构框架。软件开发包括需求、设计、编码和测试等阶段,有时也包括维护阶段。软件开发模型能清晰、直观地表达软件开发全过程,明确规定了要完成的主要活动和任务,用来作为软件项目工作的基础。对于不同的软件系统,可以采用不同的开发方法、使用不同的程序设计语言以及各种不同技能的人员参与工作、运用不同的管理方法和手段等,以及允许采用不同的软件工具和软件工程环境。
最早出现的软件开发模型是 1970 年W·Royce提出的瀑布模型。该模型给出了固定的顺序,将生存期活动从上一个阶段向下一个阶段逐级过渡,如同流水下泻,最终得到所开发的软件产品,投入使用。但计算拓广到统计分析、商业事务等领域时,大多数程序采用高级语言(如FORTRAN、COBOL等)编写。瀑布模型也存在着缺乏灵活性、无法通过并发活动澄清本来不够确切的需求等缺点。
下面介绍几种典型的开发模型。
遗憾的是,许多产品都是使用“边做边改”模型来开发的。在这种模型中,既没有规格说明,也没有经过设计,软件随着客户的需要一次又一次地不断被修改。
在这个模型中,开发人员拿到项目立即根据需求编写程序,调试通过后生成软件的第一个版本。在提供给用户使用后,如果程序出现错误,或者用户提出新的要求,开发人员重新修改代码,直到用户满意为止。
这是一种类似作坊的开发方式,对编写几百行的小程序来说还不错,但这种方法对任何规模的开发来说都是不能令人满意的,其主要问题在于:
①缺少规划和设计环节,软件的结构随着不断修改越来越糟,导致无法继续修改。
②忽略需求环节,给软件开发带来很大的风险。
③没有考虑测试和程序的可维护性,也没有任何文档,软件的维护十分困难。
1970 年Winston Royce提出了著名的“瀑布模型”,直到 20 世纪 80 年代早期,它一直是唯一被广泛采用的软件开发模型。瀑布模型将软件生命周期划分为制定计划、需求分析、软件设计、程序编写、软件测试和运行维护等六个基本活动,并且规定了它们自上而下、相互衔接的固定次序,如同瀑布流水,逐级下落。
在瀑布模型中,软件开发的各项活动严格按照线性方式进行,当前活动接受上一项活动的工作结果,实施完成所需的工作内容。当前活动的工作结果需要进行验证,如果验证通过,则该结果作为下一项活动的输入,继续进行下一项活动,否则返回修改。
瀑布模型强调文档的作用,并要求每个阶段都要仔细验证。但是,这种模型的线性过程太理想化,已不再适合现代的软件开发模式,几乎被业界抛弃,其主要问题在于:
①各个阶段的划分完全固定,阶段之间产生大量的文档,极大地增加了工作量。
②由于开发模型是线性的,用户只有等到整个过程的末期才能见到开发成果,从而增加了开发的风险。
③早期的错误可能要等到开发后期的测试阶段才能发现,进而带来严重的后果。
我们应该认识到,“线性”是人们最容易掌握并能熟练应用的思想方法。当人们碰到一个复杂的“非线性”问题时,总是千方百计地将其分解或转化为一系列简单的线性问题,然后逐个解决。一个软件系统的整体可能是复杂的,而单个子程序总是简单的,可以用线性的方式来实现,否则干活就太累了。线性是一种简洁,简洁就是美。当我们领会了线性的精神,就不要再呆板地套用线性模型的外表,而应该用活它。例如,增量模型实质就是分段的线性模型,螺旋模型则是弯曲了的线性模型,在其他模型中也能够找到线性模型的影子。
快速原型模型的第一步是建造一个快速原型,实现客户或未来的用户与系统的交互,用户或客户对原型进行评价,进一步细化待开发软件的需求。通过逐步调整原型使其满足客户的要求,开发人员可以确定客户的真正需求是什么;第二步则在第一步的基础上开发客户满意的软件产品。
显然,快速原型方法可以克服瀑布模型的缺点,减少由于软件需求不明确带来的开发风险,具有显著的效果。
快速原型的关键在于尽可能快速地建造出软件原型,一旦确定了客户的真正需求,所建造的原型将被丢弃。因此,原型系统的内部结构并不重要,重要的是必须迅速建立原型,随之迅速修改原型,以反映客户的需求。
增量模型又称演化模型。与建造大厦相同,软件也是一步一步建造起来的。在增量模型中,软件被作为一系列的增量构件来设计、实现、集成和测试,每一个构件是由多种相互作用的模块所形成的提供特定功能的代码片段构成。增量模型在各个阶段并不交付一个可运行的完整产品,而是交付满足客户需求的一个子集的可运行产品。整个产品被分解成若干个构件,开发人员逐个构件地交付产品,这样做的好处是软件开发可以较好地适应变化,客户可以不断地看到所开发的软件,从而降低开发风险。但是,增量模型也存在以下缺陷:
①由于各个构件是逐渐并入已有的软件体系结构中的,所以加入构件必须不破坏已构造好的系统部分,这需要软件具备开放式的体系结构。
②在开发过程中,需求的变化是不可避免的。增量模型的灵活性可以使其适应这种变化的能力大大优于瀑布模型和快速原型模型,但也很容易退化为边做边改模型,从而使软件过程的控制失去整体性。
在使用增量模型时,第一个增量往往是实现基本需求的核心产品。核心产品交付用户使用后,经过评价形成下一个增量的开发计划,它包括对核心产品的修改和一些新功能的发布。这个过程在每个增量发布后不断重复,直到产生最终的完善产品。
例如,使用增量模型开发文字处理软件。可以考虑,第一个增量发布基本的文件管理、编辑和文档生成功能;第二个增量发布更加完善的编辑和文档生成功能;第三个增量实现拼写和文法检查功能;第四个增量完成高级的页面布局功能。
1988 年,Barry Boehm正式发表了软件系统开发的“螺旋模型”,它将瀑布模型和快速原型模型结合起来,强调了其他模型所忽视的风险分析,特别适合于大型复杂的系统。螺旋模型沿着螺线进行若干次迭代,图中的 4 个象限代表了以下活动:
①制定计划:确定软件目标,选定实施方案,弄清项目开发的限制条件。
②风险分析:分析评估所选方案,考虑如何识别和消除风险。
③实施工程:实施软件开发和验证。
④客户评估:评价开发工作,提出修正建议,制定下一步计划。
螺旋模型由风险驱动,强调可选方案和约束条件从而支持软件的重用,有助于将软件质量作为特殊目标融入产品开发之中。但是,螺旋模型也有一定的限制条件,具体如下:
①螺旋模型强调风险分析,但要求许多客户接受和相信这种分析,并做出相关反应是不容易的,因此,这种模型往往适应于内部的大规模软件开发。
②如果执行风险分析将大大影响项目的利润,那么进行风险分析毫无意义,因此,螺旋模型只适合于大规模软件项目。
③软件开发人员应该擅长寻找可能的风险,准确地分析风险,否则将会带来更大的风险。
一个阶段首先是确定该阶段的目标,完成这些目标的选择方案及其约束条件,然后从风险角度分析方案的开发策略,努力排除各种潜在的风险,有时需要通过建造原型来完成。如果某些风险不能排除,该方案立即终止,否则启动下一个开发步骤。最后,评价该阶段的结果,并设计下一个阶段。
演化模型是一种全局的软件(或产品)生存周期模型。属于迭代开发方法。该模型可以表示为:
第一次迭代(需求→设计→实现→测试→集成)→反馈→第二次迭代(需求→设计→实现→测试→集成)→反馈→……
即根据用户的基本需求,通过快速分析构造出该软件的一个初始可运行版本,这个初始的软件通常称为原型,然后根据用户在使用原型的过程中提出的意见和建议对原型进行改进,获得原型的新版本。重复这一过程,最终可得到令用户满意的软件产品。采用演化模型的开发过程,实际上就是从初始的原型逐步演化成最终软件产品的过程。演化模型特别适用于对软件需求缺乏准确认识的情况。
喷泉模型(也称面向对象的生存期模型,OO模型)与传统的结构化生存期比较,具有更多的增量和迭代性质,生存期的各个阶段可以相互重叠和多次反复,而且在项目的整个生存期中还可以嵌入子生存期。就像水喷上去又可以落下来,可以落在中间,也可以落在最底部。
智能模型拥有一组工具(如数据查询、报表生成、数据处理、屏幕定义、代码生成、高层图形功能及电子表格等),每个工具都能使开发人员在高层次上定义软件的某些特性,并把开发人员定义的这些软件自动地生成为源代码。
这种方法需要四代语言(4GL)的支持。4GL不同于三代语言,其主要特征是用户界面极端友好,即使没有受过训练的非专业程序员,也能用它编写程序;它是一种声明式、交互式和非过程性编程语言。4GL还具有高效的程序代码、智能缺省假设、完备的数据库和应用程序生成器。市场上流行的 4GL(如Foxpro等)都不同程度地具有上述特征。但 4GL主要应用于事务信息系统的中、小型应用程序的开发。
过程开发模型又称混合模型(Hybrid Model),或元模型(meta-model),把几种不同模型组合成一种混合模型,它允许一个项目能沿着最有效的路径发展,这就是过程开发模型(或混合模型)。实际上,一些软件开发单位都是使用几种不同的开发方法组成他们自己的混合模型。
快速应用开发(RAD)模型是一个增量型的软件开发过程模型,强调极短的开发周期。RAD模型是瀑布模型的一个“高速”变种,通过大量使用可复用构件,采用基于构件的建造方法赢得快速开发。如果需求理解得好且约束了项目的范围,随后是数据建模、过程建模、应用生成、测试及反复。
RAD模型各个活动期所要完成的任务如下:
①业务建模:以什么信息驱动业务过程运作、要生成什么信息、谁生成它、信息流的去向是哪里、由谁处理,可以辅之以数据流图。
②数据建模:为支持业务过程的数据流找数据对象集合,定义数据对象属性,与其他数据对象关系构成数据模型,可辅之以E-R图。
③过程建模:使数据对象在信息流中完成各业务功能。创建过程以描述数据对象的增加、修改、删除、查找,即细化数据流图中的处理框。
④应用程序生成:利用第四代语言(4GL)写出处理程序,重用已有构件或创建新的可重用构件,利用环境提供的工具自动生成并构造出整个应用系统。
⑤测试与交付:由于大量重用,一般只做系统测试,但新创建的构件还是要测试的。
每个软件开发组织应该选择适合于该组织的软件开发模型,并且应该随着当前正在开发的特定产品特性而变化,以减少所选模型的缺点,充分利用其优点。下面列出了几种常见模型的优缺点。
表 1.6 常见模型优缺点表
软件测试作为软件工程中的重要一环,是项目成败的一个不可忽略的内容。
不同的软件企业采用不一样的开发模式,不同的项目采用不同的开发过程,不同的产品适合采用不同的软件工程方法。那么对于不同的软件开发模式或开发过程,测试人员如何找准自己的位置,如何更好地配合这个过程呢?
在 20 世纪 60 年代左右,美国军方在对联邦项目(由承包商完成的)的一项统计中,发现软件行业较为混乱,软件质量不高。但是,它又要用这些软件承包商开发的软件。后来,美国软件工程研究所(SEI)受美国国防部委托立项,要求提出一个模型,以评估软件承包商的能力,协助软件组织改进过程,提高过程能力。
项目负责人是:Watts Humphrey(CMM之父)。研究了大约 1 年多,拿出了他们的成果,于 1987 年发表承包商软件工程师能力评估方法,提出初始框架,根据这个框架来评估软件承包商的能力。那个时候,这个框架不叫CMM,而是叫作PMM(Process Maturity Model,流程成熟度模型),用于规范流程。
1991 年推出CMM1.0 版,1993 年提出CMM1.1 版,维护到了 2000 年左右,由于不同行业的软件不同,分类又有很多,又制定了不同的模型。
就像江湖一样,虽然分为各个流派,但总有人要一统江湖,那就是CMMI(Capability Maturity Model Integration For Software,软件能力成熟度模型集成),是在CMM(Capability Maturity Model For Software,软件能力成熟度模型)的基础上发展而来的。
按照软件工程的两大流派,可以分成“流程派”和“个体派”。“流程派”以CMMI和ISO为代表,强调按既定的流程工作。“个体派”以新兴的敏捷开发为代表,强调人在过程中发挥价值。
CMM:其英文全称为Capability Maturity Model for Software,英文缩写为SW-CMM,简称CMM。它是对于软件组织在定义、实施、度量、控制和改善其软件过程的实践中各个发展阶段的描述。CMM的核心是把软件开发视为一个过程,并根据这一原则对软件开发和维护进行过程监控和研究,以使其更加科学化、标准化、使企业能够更好地实现商业目标。
那么CMM是如何评估软件承包商能力的呢?从以下几个方面展开:
①软件流程能力:遵循标准的软件流程,有多大可能达到预计的结果。软件流程能力提供一种有效的手段,可以预计软件组织承担某个项目最有可能出现的结果。
②软件流程性能:遵循标准的软件流程,真正达到的结果是怎么样的,换而言之,软件流程能力是表示期望的结果,而软件流程性能表述的是软件表达的实际结果。
③软件流程成熟度:指一个特定的流程,在多大程度上被明白无误地定义、管理、衡量和控制,以及软件表达的效果是怎么样的。一个软件组织的软件流程成熟度是预示着它的软件流程能力有多大的发展潜力,这不仅指它的软件流程的丰富性、完备性,并且代表软件流程要做到一致。
CMMI全称为Capability Maturity Model Integration,即能力成熟度模型集成(也称为软件能力成熟度集成模型),是美国国防部的一个设想,其目的是帮助软件企业对软件工程过程进行管理和改进,增强开发与改进能力,从而能按时地、不超预算地开发出高质量的软件。其所依据的想法是:只要集中精力持续努力去建立有效的软件工程过程的基础结构,不断进行管理的实践和过程的改进,就可以克服软件开发中的困难。
CMM是一种用于评价软件承包能力并帮助其改善软件质量的方法,侧重于软件开发过程的管理及工程能力的提高与评估。CMM分为 5 个等级:1 级为初始级,2 级为可重复级,3 级为已定义级,4 级为已管理级,5 级为优化级。
CMM/CMMI将软件过程的成熟度分为 5 个等级,以下是 5 个等级的基本特征:
①初始级(initial)。工作无序,项目进行过程中常放弃当初的计划。管理无章法,缺乏健全的管理制度。开发项目成效不稳定,项目成功主要依靠项目负责人的经验和能力,他一旦离去,工作秩序面目全非。
②可重复级(Repeatable)。管理制度化,建立了基本的管理制度和规程,管理工作有章可循。初步实现标准化,开发工作比较好地按标准实施。变更依法进行,做到基线化,稳定可跟踪,新项目的计划和管理基于过去的实践经验,具有重复以前成功项目的环境和条件。
③已定义级(Defined)。开发过程,包括技术工作和管理工作,均已实现标准化、文档化。建立了完善的培训制度和专家评审制度,全部技术活动和管理活动均可控制,对项目进行中的过程、岗位和职责均有共同的理解。
④已管理级(Managed)。产品和过程已建立了定量的质量目标。开发活动中的生产率和质量是可量度的。已建立过程数据库。已实现项目产品和过程的控制。可预测过程和产品质量趋势,如预测偏差,实现及时纠正。
⑤优化级(Optimizing)。可集中精力改进过程,采用新技术、新方法。拥有防止出现缺陷、识别薄弱环节以及加以改进的手段。可取得过程有效性的统计数据,并可根据数据进行分析,从而得出最佳方法。
CMMI的二级关键域包括软件质量保证,主要需要解决的问题是培训、测试、技术评审等。这是任何一个想从混乱的初始级别上升到可重复级别的软件组织需要关注和解决的问题。
对于软件测试,在这个阶段需要考虑的是测试是否有规范的流程,与开发人员如何协作,Bug如何记录和跟踪。还需要关注测试人员的技能水平是否达到一定的要求,是否建立起培训机制。