1.4 军用软件生存周期
20世纪60年代末提出软件工程概念后,人们在探索如何在实施软件工程的过程中逐步认识到,要得到高质量的软件,只搞好编程工作是远远不够的,编程之前,还必须进行软件需求分析和软件设计,且其质量对最终软件产品的质量更具有决定作用;而且程序编完之后,还要进行重要性并不次于编程工作,而工作量比编程大得多的软件测试工作。直到20世纪70年代中期,软件生存周期的概念才逐渐形成。此后,人们又进一步探索软件生存周期究竟有哪些过程,以及如何实施这些过程才能取得令人满意的结果等问题。到了20世纪90年代,才出现了关于软件生存周期的标准,如IEEE 1074—2006《开发软件项目生存周期过程》、ISO/IEC 12207—2017《系统和软件工程 软件生存周期过程》。随着软件工程技术的发展,软件生存周期过程也在不断丰富,目前这方面的研究仍在继续。
如同任何事物一样,军用软件也有孕育、诞生、成长、成熟、衰亡的生存过程,我们称其为军用软件的生存周期。
1.4.1 软件生存周期
软件生存周期是由工程中产品生存周期的概念得来的。引入软件生存周期概念对于软件生产的管理、进度控制有着非常重要的意义,使软件生产有相应的模式、流程、工序和步骤。
在GB/T 11457—2006《信息技术 软件工程术语》中“软件生存周期”的定义为:“从设计软件产品开始到产品不能再使用时为止的时间周期。软件生存周期通常包括需求阶段、设计阶段、实现阶段、测试阶段、安装和验收阶段、运行和维护阶段,有时还包括引退阶段。”
国家标准GB/T 8566—2007《信息技术 软件生存周期过程》将软件生存周期划分为:可行性研究、项目计划、需求分析、总体设计、详细设计、编码实现(包括单元测试)、集成测试、确认测试、系统运行和维护。
软件生存周期的各阶段有不同的划分。软件规模、种类、开发模式、开发环境和开发方法都影响软件生存周期的划分。在划分软件生存周期阶段时,应遵循一定的规则,如各阶段的任务应尽可能相对独立,同一阶段各项任务的性质应尽可能相同,从而降低每个阶段任务的复杂程度,简化不同阶段之间的联系,有利于软件项目开发的组织和管理。
通过归纳,可以将软件生存周期分为 3 个大的阶段,即软件定义阶段,软件开发阶段和软件维护阶段。
1.软件定义阶段
软件定义阶段必须回答的问题是:需要软件解决的问题是什么?如果不知道问题是什么就试图解决这个问题,只会白白浪费时间和金钱,最终得出的结果很可能是毫无意义的。软件定义阶段是软件项目的早期阶段,主要是由软件分析人员和用户合作,针对有待开发的软件系统进行分析规划和规格描述,确定软件做什么,为今后的软件开发做好准备。软件定义时期的任务是了解用户的需求,确定项目的总体目标,考察和分析项目的可行性,导出实现项目目标应该采取的策略,以及系统必须完成的功能,并估计项目需要的资源和成本,制定工程进度表等。这个时期需要分阶段地进行以下工作:
(1)软件任务立项。软件项目一般始于任务立项,并需要以立项报告的形式针对项目的名称、性质、目标、意义和规模做出回答,以此获得对准备着手开发的软件系统的概括性描述。
(2)可行性研究。在软件任务立项报告被批准后,接着需要进行项目可行性分析。这个阶段要回答的关键问题是:“对于上一个阶段所确定的目标有行得通的解决办法吗?”为了回答这个问题,系统分析员需要在较抽象的高层次上进行分析和设计,对任务立项阶段所确定的目标进行可行性和必要性研究。可行性研究主要从技术可行性、经济可行性、操作可行性等方面进行分析,寻求一种或多种在技术、经济、操作和法律等各方面可行的解决方案,对各种可能方案做出必要的成本/效益分析,据此提出可行性分析报告,作为是否继续进行该项工程的依据。
(3)需求分析。这个阶段的任务仍然不是具体地解决问题,而是准确地确定“为了解决这个问题,目标系统必须做什么”,主要是确定目标系统必须具备哪些功能。需求分析要求以用户需求为依据,从功能、性能、数据、操作等多个方面,对软件系统给出完整、准确、具体的描述,用于确定软件规格。其结果将以软件需求规格说明书的形式提交。软件需求分析是从软件定义到软件开发的关键步骤,其结论不仅是今后软件开发的基本依据,同时也是今后用户对软件产品进行验收的基本依据。
(4)制订项目计划。在确定项目可以进行以后,就需要针对项目的开展,从人员、组织、进度、资金、设备等多方面进行合理的规划,并以项目开发计划书的形式提交书面报告。项目开发计划涉及实施项目的各个环节,计划的合理性和准确性将关系项目的成败。
2.软件开发阶段
软件开发阶段的任务是设计实现已定义的、并经过需求分析的软件系统。通常将软件开发阶段划分为软件设计、软件实现和软件测试3个阶段。其中,软件设计又可分为总体设计和详细设计,编码是对软件的实现。软件测试又可分为单元测试、集成测试、确认测试和系统测试。将设计和实现分开的目的是在开发初期集中精力搞好软件结构设计,避免过早地为实现细节分散精力。
(1)总体设计。总体设计是建立系统的总体结构,从总体上对软件的结构、接口、全局数据结构、数据环境等给出设计说明,并以概要设计说明书的形式提交书面报告,其结果将成为详细设计与软件实现的基本依据。模块是总体设计时的基本元素,因此,总体设计的工作主要体现在模块的构成与模块接口等方面。结构化设计中的函数、过程,面向对象设计中的类、对象,它们都是模块。总体设计时并不需要说明模块的内部细节,但是需要进行全部的有关它们构造的定义,包括功能特性、数据特征、接口等。模块的独立性是一个有关质量的重要技术指标,可以使用模块的内聚性、耦合度等定性参数对模块独立性进行度量。
(2)详细设计。详细设计以总体设计为依据。它主要是确定软件结构中每个模块的内部细节,为编写程序提供最直接的依据。详细设计需要从实现每个模块功能的程序算法和模块内部的局部数据结构等细节内容上给出设计说明,并以详细设计说明书的形式提交书面报告。
(3)编码。编码是对软件的实现,以获得源程序基本模块为目标。编码必须按照详细设计说明书的要求逐个实现每个模块的功能。在基于软件工程的软件开发过程中,编码往往只是语言转译工作,即把详细设计中的算法描述语言转换成某种适当的程序设计语言。
(4)单元测试。为了方便调试,针对基本模块的单元测试也往往和编码结合在一起进行。单元测试也以详细设计说明书为依据,用于检查每个基本模块在功能、算法与数据结构上是否符合设计要求。
(5)集成测试。集成测试是根据总体设计中的软件结构,把经过单元测试的模块,按照某种选定的集成策略将系统组装起来,在组装过程中对程序进行必要的测试。
(6)确认测试。确认测试是以用户为主体,以需求规格说明书中对软件的定义为依据,由此对软件的各项规格进行逐项确认,以确保已经完成的软件系统与需求规格的一致性。在完成对软件的验收后,软件系统就可以交付使用了,开发人员需要以项目开发总结报告的形式对项目进行总结。
(7)系统测试。系统测试是将已经确认的软件、硬件等其他元素结合在一起,进行系统的各种集成测试和技术测试。其目的是通过与系统的需求相比较,发现所开发的软件与用户需求不符或矛盾的地方。系统测试是根据需求规格说明书来设计测试用例的。
3.软件维护阶段
运行阶段的任务是保障软件的正常运行,并对软件进行维护。为了排除软件系统中可能隐含的错误,适应用户需求及系统操作环境的变化,需要继续对系统进行修改或扩充。为了使系统具有较长的生命力,对于每项维护活动都应准确地记录下来,作为正式的文档资料加以保存。在适当的时候要对软件进行评价,如果经过修改或补充,软件仍不能适应新的需求,则该软件就应被新的软件所替代。
研究软件生存周期的目的是为了科学、有效地组织和管理软件的生产,从而使软件生产更可靠、更经济。采用软件生存周期来划分软件的工程化开发,使软件开发分阶段依次进行。前一个阶段任务的完成是后一个阶段工作的前提和基础,而后一个阶段通常将前一个阶段提出的方案进一步具体化。每个阶段结束之前都要接受严格的技术评审和管理评审。采用这种划分,使得每个阶段的工作相对独立,有利于简化问题,且便于不同人员分工协作。而且其严格的科学的评审制度保证了软件的质量,提高了软件的可维护性,从而大大提高了软件开发的生产率和成功率。
1.4.2 典型生存周期模型
软件生存周期模型提供了一个框架,以便描述在软件生存周期内进行软件开发、操作和维护所需要实施的过程、活动和任务。由于工作对象和范围的不同,软件开发人员经验的差异,所采用的软件生存周期模型也有所不同。
软件工程过程没有规定一个特定的软件生存周期模型或软件开发方法,各个软件开发机构可以为自己的开发项目选择一种生存周期模型,并将软件工程过程所包含的各种过程、活动和任务映射到该模型中,也可以选择和使用软件开发方法来执行适合于其软件项目的活动和任务。
美国国家航空航天局(NASA)指出:“在整个 NASA 中,从多年的软件工程实践中吸取的一个重要教训是,没有一个单一的解决方法能够解决所有的问题。没有一个生存周期、分析和设计方法、测试方法、产品评估方法适合于所有的NASA软件项目。”因此,在实际应用中,应根据具体情况选择适当的软件生存周期模型。
在GB/T 8566—2007《信息技术 软件生存周期过程》中描述了软件生存周期过程的体系结构,但没有规定一个特定的生存周期模型或软件开发方法。该标准指出“采用本标准的各方负责为软件项目选择一个生存周期模型,并把本标准所述的过程、活动和任务映射到该模型中。各参与方还有责任选择和应用软件开发方法,并执行适合于软件项目的活动和任务”。
下面介绍几种典型的软件生存周期模型。
1.瀑布模型
军用软件工程最初采用的软件设计模型,就是根据GJB 437规定反映生存周期法的瀑布模型,也称线性顺序模型、传统生存周期模型。该模型提出了软件开发系统化、顺序化的方法。
瀑布模型规定了各项软件工程活动,包括制订开发计划、进行需求分析和说明、软件设计、程序编码、测试及运行维护,并且规定了它们自上而下,相互衔接的固定次序,如同瀑布流水,逐级下落。如图1.1所示。
然而软件开发的实践表明,上述各项活动之间并非完全是自上而下,呈线性图式。实际情况是,每项开发活动均处于一个质量环(输入—处理—输出—评审)中。从上一项活动接受本项活动的工作对象,作为输入;利用这一输入实施本项活动应完成的内容;给出本项活动的工作成果,作为输出传给下一项活动;对本项活动实施的工作进行评审。
只有当其工作得到确认,才能继续进行下一项活动,在图1.1中用向下的箭头表示;否则返工,在图1.1中用向上的箭头表示。
图1.1 软件生存周期的瀑布模型
软件维护在软件生存周期中有它的特点。一方面,维护的具体要求是在软件投入运行以后提出来的,经过评价,确定变更的必要性,才进入维护工作。另一方面,所谓维护中对软件的变更仍然要经历上述软件生存周期在开发中已经历过的各项活动。事实上,有人把维护称为软件的二次开发,正是出于这种考虑。由于软件在投入使用以后可能经历多次变更,为把开发活动和维护活动区别开来,便有了b形的软件生存周期表示,如图1.2所示。它与前述的软件生存周期循环一样,都是软件生存周期瀑布模型的变种。
瀑布模型为软件开发和软件维护提供了一种有效的管理模式。根据这一模式制订开发计划、进行成本预算、组织开发力量,以项目的阶段评审和文档控制为手段有效地对整个开发过程进行指导,从而保证软件产品及时交付,并达到预期的质量要求。与此同时,瀑布模型在大量的软件开发实践中也逐渐暴露出它的缺点。其中最为突出的缺点是该模型缺乏灵活性,特别是无法解决软件需求本身不明确或不准确的问题。
图1.2 具有维护循环的软件生存周期
这些问题的存在会给软件开发带来严重影响,最终可能导致开发出的软件并不是用户真正需要的软件,并且这一点在开发过程完成后才有所察觉。面对这些情况,无疑需要进行返工或是不得不在维护中纠正需求的偏差。但无论上述哪种情况都必须付出高额的代价,并将为软件开发带来不必要的损失。另外,随着软件开发项目规模的日益庞大,由于瀑布模型不够灵活等缺点引发出的上述问题显得更为严重。
为弥补瀑布模型的不足,近年来已经提出了多种其他模型。
2.演化模型
由于在项目开发的初始阶段人们对软件的需求认识常常不够清晰,因而使得开发项目难于做到一次开发成功,出现返工再开发在所难免。因此,可以先做试验开发,其目标只是在于探索可行性,弄清软件需求;然后在此基础上获得较为满意的软件产品。通常把第一次得到的试验性产品称为原型,如图1.3所示。
图1.3 演化模型
演化模型又称为增量模型。软件在该模型中是被逐渐开发出来的,开发出一部分,向用户展示一部分,可使用户及早看到部分软件,及早发现问题。或者先开发一个原型软件,完成部分主要功能,展示给用户并征求意见,然后逐步完善,最终获得满意的软件产品。该模型具有较大的灵活性,适合于软件需求不明确,设计方案有一定风险的软件项目。
演化模型从需求分析开始。软件开发人员与用户一起定义待开发软件系统的总目标,定义需求,确定软件的工作范围。然后快速设计软件中对使用者可见部分的表示,进而建造原型,再让用户或客户评估原型,根据评估结果,修改和细化待开发软件系统的需求,使之满足用户的需求。这个过程是一个迭代的过程。
演化模型的优点是:
(1)演化模型与传统的软件生存周期法比较,能够得到更良好的软件需求,它不仅能够处理模糊的需求,而且开发人员与用户可通过原型充分进行交流。
(2)原型系统可作为培训环境。它有利于使用户的培训和开发同步。
(3)演化模型给用户提供了机会,以更改用户原来设想的不尽合理的最终系统。
(4)演化模型可以低风险地开发柔性较大的计算机系统。
(5)演化模型使得开发出来的最终系统更容易维护,对用户更友好。
(6)演化模型可以降低总的开发费用,缩短开发时间。
演化模型的缺点是:
(1)对于开发人员不熟悉的领域,演化模型可能误导开发者把系统的次要部分当作主要框架,开发出不切题的原型。
(2)原型迭代不收敛于开发者预定的目标。为了消除错误,每次更改使得次要部分越来越大,淹没了系统的主要部分。
(3)原型过快地收敛于需求集合,使得某些基本方面被忽视。
(4)资源规划和管理比较困难,随时更新文档也会带来许多麻烦。
(5)长期在原型环境下开发,只注意得到令人满意的原型,容易遗忘用户环境与实际客户环境之间的差别。
3.螺旋模型
对于复杂的大型软件,开发一个原型往往达不到要求。螺旋模型将瀑布模型与演化模型结合起来,并且加入两种模型均忽略了的风险分析。
软件风险是普遍存在于任何软件开发项目中的实际问题。对于不同的项目,其差别只是风险有大有小而已。在制订软件开发计划时,系统分析员必须回答:项目的需求是什么,需要投入多少资源,以及如何安排开发进度等一系列问题。然而,若要他们当即给出准确无误的回答是不容易的,甚至几乎是不可能的,但系统分析员又不可能完全回避这一问题。凭借经验的估计出发给出初步的设想便难免带来一定风险。实践表明,项目规模越大,问题越复杂,资源、成本、进度等因素的不确定性越大,承担项目所冒的风险也越大。因此,风险是软件开发不可忽视的潜在不利因素,它可能在不同程度上损害软件开发过程或软件产品的质量。软件风险控制的目标是在造成危害之前,及时对风险进行识别、分析,采取对策,进而消除或减少风险的损害。
螺旋模型沿着螺线旋转,如图1.4所示,笛卡儿坐标系的4个象限上分别表达了4个方面的活动。
图1.4 螺旋模型
(1)制订计划——确定软件目标,选定实施方案,弄清项目开发的限制条件。
(2)风险分析——分析评价所选方案,考虑如何识别和消除风险。
(3)实施工程——实施软件开发。
(4)客户评估——评价开发工作,提出修正建议。
沿螺线自内向外,每旋转一圈便开发出更为完善的一个新软件版本。例如,在第一圈,确定了初步的目标、方案和限制条件以后,转入第Ⅰ象限,对风险进行识别和分析。如果风险分析表明,需求有不确定性,那么在工程象限(第Ⅳ象限)内,所建的原型会帮助开发人员和客户,考虑其他开发模型,并对需求做进一步修正。客户对工程成果做出评价之后,给出修正建议。在此基础上需要再次计划,并进行风险分析。在每圈螺线上,风险分析的终点做出是否继续下去的判断。假如风险过大,开发者和用户无法承受,项目有可能终止。在多数情况下沿螺线的活动会继续下去,自内向外,逐步延伸,最终得到所期望的系统。
如果软件开发人员对所开发项目的需求已有了较好的理解或较大的把握,则无须开发原型,可采用普通的瀑布模型,这在螺旋模型中可认为是单圈螺线。与此相反,如果对所开发项目的需求理解较差,则需要开发原型,甚至需要不止一个原型的帮助,那就需要经历多圈螺线。在这种情况下,外圈的开发包含了更多的活动,也可能某些开发采用了不同的模型。
螺旋模型适合大型软件的开发,应该说它是最为实际的方法,它吸收了软件工程演化的概念,使得开发人员和客户对每个演化层出现的风险有所了解,继而做出应有的反应。图1.5给出了螺旋模型的另一图式。
螺旋模型的优越性比起其他模型来说是明显的,但并不是绝对的。要求许多客户接受和相信演化方法并不容易。这个模型的使用需要具有相当丰富的风险评估经验和专门知识。如果项目风险较大,又未能及时发现,势必造成重大损失。
图1.5 螺旋模型的另一图式
1.4.3 生存周期模型选择原则
目前,大多数软件开发项目都采用改进的瀑布模型作为规范化开发的基础,其主要原因是:
(1)软件开发单位的软件工程工作尚处于初级阶段,软件开发人员和管理人员既缺乏经验,又无历史数据可供借鉴,因此需要一种比较简单易行的组织方式。
(2)结构化方法学是系统工程中最成熟的方法学,目前大多数软件开发都以结构化开发方法学为基础。
(3)在与结构化方法学相适应的生存周期模型中,改进的瀑布模型最为简单实用,行之有效。
(4)有关软件开发的现行国家标准和国家军用标准都是以瀑布模型为基础制定的。
随着计算机技术的迅猛发展,新型软件支持工具和环境的不断推出,软件开发单位在软件开发经验和数据方面的日益积累,软件开发人员业务素质的逐步提高,可以预料,未来软件开发将会采用更为先进的生存周期模型和技术。因此,在开发一个软件项目时,首先应当为其选定适当的软件生存周期模型,然后按选定的模型开展管理和技术工作,选用相应的标准和工具。
对于一个软件开发项目,选择生存周期模型时,一般应遵循下述原则:
(1)生存周期模型应与软件项目的特点(如软件规模和复杂性)相适应。
(2)生存周期模型应与所采用的软件开发技术(如结构化方法)相适应。
(3)生存周期模型应满足整个应用系统的开发进度要求。
(4)生存周期模型应有助于控制和消除软件开发风险。
(5)生存周期模型应有可用的计算机辅助工具的支持。
(6)生存周期模型应与用户和软件开发人员的知识和技能水平相适应。
(7)生存周期模型应有利于软件开发的管理和控制。
在为一个具体项目选择软件生存周期时,通常应考虑项目的特性(如系统的功能和复杂性,软件的规模和复杂性,需求的稳定性,以前开发结果的使用,开发策略和硬件的可用性等),通过选择每个过程的活动、规定活动的顺序和分配给活动的责任来定义的软件生存周期。
一个项目可以定义一个或多个软件生存周期。RTCA DO-178B《机载系统和设备合格审定中的软件考虑》给出了一个项目的示例。该项目使用了4种不同的软件生存周期,具有不同软件生存周期的单个软件由4个软件部件(W、X、Y和Z)组成,其开发过程如下:通过开发软件需求,软件部件W实施一系列系统需求,使用那些需求来确定软件设计,将设计转换为源代码,并把软件部件W集成到硬件中;软件部件X是对在已经合格审定的航空器或发动机中使用的以前开发的软件的使用说明;软件部件 Y 利用了能从软件需求直接编码的、简单的、划分的功能;软件部件Z使用了原型策略进行软件开发,其目的是为了更好地理解软件需求,并减少开发和技术的风险,它采用原始需求作为开发原型的基础,并使原型在代表被开发系统的、预定的使用环境中进行评估,并用评估的结果来改进软件需求,进而开发出该软件部件,如图1.6所示。
图1.6 使用4种软件生存周期的项目示例
R—软件需求分析;D—软件设计;C—软件实现;I—软件集成。