Software Process Models

简介

软件过程是构建软件的一系列活动,这些活动包含了软件从无到有的开发过程。然而越来越多的新型软件都是通过扩展已有的系统或集成现有的软件组件来完成开发。

软件过程模型是一种软件过程的抽象表现,每种过程模型会从一种特殊的视角来表示一种过程,因此仅仅会提供一种局部的信息来反映该过程。本节将介绍一些常用的过程模型,然后从架构的角度来说明他们,因此,我们将探讨每个过程的框架结构而不会涉及到具体的细节活动。

瀑布模型

第一种发布的软件开发过程模型衍生自很多系统工程的过程中,这种模型如图1.


app_process 指定进程名 软件process_瀑布模型


此模型由于是从一个阶段到另一个阶段的层级形式,所以被称为瀑布模型或软件生命周期模型。瀑布模型包含的基本开发活动有:

1.      需求分析和定义:由用户建立系统服务、受限约束以及实现目标,然后定义具体细节和指定系统规范。

2.      系统和软件设计:系统设计过程把需求划分为硬件和软件系统两部分,并建立整体的系统架构。而软件设计则会确定并描述系统抽象定义关系。

3.      实现和单元测试:在此阶段,软件设计会由程序集或程序单元来实现,而单元测试则是验证每个模块是否满足需求定义。

4.      集成和系统测试:把独立的程序单元集成为一个完整的系统并测试其功能是否符合需求规范。

5.      使用和维护:一般的,这是一个长期阶段,安装好系统后并交付用户使用。维护则包含有修改错误,改进系统实现。

一般而言,每个阶段都会形成很多文档,上一个阶段没有完成时,则不能开始下一个阶段。事实上,这些过程会相互重叠并相互补充信息。在设计阶段,会确认需求中的问题而在编码阶段来寻查到具体的问题。这些过程不仅仅是一种线性模型,而且还会有开发活动的不断迭代。

由于文档生成的会有成本,所以迭代会带来昂贵的代价并涉及到重大的返工。完成一部分迭代开发后,冻结部分开发活动,如需求分析,然后再继续后续开发阶段。有问题留待以后解决,置之不顾,或者通过编程绕过去,这种过早的冻结需求分析可能会不满足用户的实际要求,这种设计会造成很糟糕的系统结构。

在瀑布模型的最后一个阶段,软件会付诸使用。在这个过程中,会发现原来的软件需求中的很多疏忽的地方,除此之外还会添加一些新的功能,因此系统会渐渐变得更适合使用。在确认这些变化时可能又会重复前期的过程。

瀑布模型的优点是各个阶段的文档化同时还适合其他过程模型,它的缺点则是把项目不灵活的划分成不同的阶段,早期阶段形成的文档约定会很难的随着用户需求的改变而变化。

因此,在系统开发时,只有需求被充分理解后或者需求不会明显的改变,就适合使用瀑布模型。然而,瀑布模型依然是很多工程项目中的一种过程模型,基于此方式的软件过程仍然常用于软件开发。

渐进式开发模型

渐进式开发:先开发一种最初的实现版本,然后交予用户并获取他们的修改意见,然后再做改进,直到重复多个版本后最终达到用户的需求。这种模式如图2。


app_process 指定进程名 软件process_数据_02


在此模型中,需求、开发、确认这些活动在实际开发过程中是相互交叉的而不是单独独立的,并根据每项活动的结果对其他活动作出快速的反馈。

关于渐进式开发模型还有两种基本的类型:

1.      探索式开发:与用户协同制定需求并逐渐完成最终目标系统。先开发部分功能,然后不断新增其他的功能。

2.      原型开发:通过原型设计来逐步理解用户的需求,原型设计能够集中表达对初期对用户需求的理解。

渐进式开发模型在系统开发过程中常常比瀑布式模型要更能够满足用户的需求,基于渐进式开发的模型的优点可以随时添加新的需求到系统中,用户改变需求后可以很有效的反应到系统中,但是从工程和管理的角度来看,渐进式模型有两点缺点:

1.      过程不明显,因此不利于项目经理完成可交付项目进度,如果项目开发过快时,生成每个版本的文档时,成本也不合算。

2.      系统结构很乱。频繁的修改会破坏系统的结构,而且后期的修改会更困难同时花费更多成本。

渐进式开发模型很适合中小型系统的开发,对于一些分组开发的大型,复杂而且周期很长的系统,这种模型就会造成特别严重的问题,因为这种方式很难建立一个稳定的系统架构,因此与其他团队集成的时候就会很困难。

针对大型的系统,常推荐采用瀑布模型和渐进式模型的混合模型来完成开发,采用原型设计来解决需求中模糊的地方,然后采用结构良好的方式来重新实现系统。对于能够确定的需求功能就采用瀑布模型,对于其他的部分如用户界面这类很难提前指定的功能,就通过使用逐步探究的方式来完成开发。

基于组件的软件工程

在大多数的软件项目中有很多软件的复用。开发人员可以把相似的设计或代码复用到相应的需求中,当需要的时候,他们通过查找和修改代码后,然后把这些代码合并到其他系统中,在渐进式开发模型中,软件的复用对于快速的开发是非常必要的。

这种非正式的软件复用常常不用考虑使用的开发过程,但是在过去的几年里,出现了一种叫基于组件的软件工程(CBSE)模型,这种模型很注重复用,如今已经变得越来越常用。

面向复用的方式依靠很多基础软件组件和一些集成框架,有时候,一些提供特殊功能如文本格式化或数值计算的系统组件还是现成可用的。CBSE的通用过程模型如图3所示。


app_process 指定进程名 软件process_app_process 指定进程名_03


在这个模型中,最初的需求分析阶段和最后的系统验证阶段可类比其他过程模型,但中间的面向复用的过程却是不同的,这些阶段如下:

1.      组件分析:在有需求规格说明的情况下,需要进行查找操作,通常都没有很精确的匹配结果,所使用的组件仅能提供一些已知的功能。

2.      需求修改:在此阶段会利用有获取到的组件信息来重新分析需求,然后修改至反映到可用的组件上。当不能修改确定的需求时,则会重新分析组件。

3.      系统重用设计:在此阶段会设计或重用系统框架,设计人员把重用的组件融入到系统框架中,如果某些组件实在是不能满足需要时,则会重新设计新的软件组件。

4.      开发和集成:在此阶段会开发不能通过第三方获取的程序,然后集成已有的和其他现成的组件来创建一个新的系统。系统集成在这个模型中只是一个软件过程而不是独立的活动。

基于组件的软件工程模型很明显的优点是可减少软件开发量以及开发成本和风险,而且常常带来很快的开发效率,然而需求却作出一些妥协,因此会导致系统可能不满足用户的实际需要。此外,还存在版本更替时不便于控制的情况。

软件测试技术

目前有许多可能的软件测试技术,他们可混合的用来提供最好的测试覆盖和结果。不管有多少测试,都不可能全面而彻底的保证程序的正确性,不可能测试所有的输入数据和代码执行路径。

根据各种条件测试技术可以分成几种类型,如下的讨论则是基于5种条件而言的:(1)可见性,(2)自动化,(3)划分条件,(4)覆盖范围,(5)脚本处理。可如图4所示:

app_process 指定进程名 软件process_app_process 指定进程名_04

测试中的条件不是独立的,比如两种划分条件可应用到黑盒测试,但是不能应用于白盒测试,脚本技术测试(回归测试、运动测试)都是自动化的测试。

黑盒测试假定测试者在测试中不知道或者忽略测序单元的功能,然后提供一些输入数据最终获取输出结果,并与预期的结果相对比。由于不要求实现技术,黑河测试可有用户来实施,因此这也是接受测试的主要技术。

黑盒技术常常测试系统的功能或者一些精确的功能输出,还应用于一些限制性测试,如系统性能或安全性测试。当程序中没有实现预期的功能需求时,黑盒测试的指定的目标就是测试该功能是否遗漏,在这种情况中,测试单元会获取数据然后触发该功能,如果失败了则会知道程序中没有代码实现。

白盒测试(代码测试)与黑盒测试相反,它更能揭示的测试的内容。用这种方式,测试者需要考虑代码然后决定输入的数据,并利用数据来选择执行路径。根据测试规格,黑盒测试必须在白盒测试之后,这样才能定位到发现的错误。

与黑盒测试不一样,白盒测试不用限制代码测试,它还适用于其他开发构件,如设计模型和规格文档。这种类型的测试使用审视技术,例如走查、审查等。用黑盒测试还能发现程序中的无作用的代码(Dead Code,程序中永远都不能被执行的语句)。

等值划分和边界值技术应用最多是在黑盒测试中,但也可以应用在白盒测试中。他们是黑盒测试技术中的一些特殊方式,以此来抵消不可能进行详尽的测试。

等值划分把输入数据划分成均匀的几组测试目标,然后假设任意一划分组的测试结果与其他组一样,因此可以忽略其他划分组的测试结果。选择一组划分数据是很困难的,因为需要充分理解数据还有符合程序的要求。从这个方面上讲,划分部分本身实际上不是黑盒测试,黑盒测试是一种提供了等值划分测试的测试技术。

边界值测试仅仅是一种附加的附加数据分析技术,它用于辅助等值划分测试。在等值划分测试中,边界值一种极端的情况,例如,如果从1到100的整数划分的话,则会执行边界分析,在这个例子中就是-1,0,+1还有99,100,101。自然地,对于-1,101就是错误的条件。

覆盖技术可以决定白盒测试执行多少代码。操作覆盖(方法覆盖)确保代码中的每个操作都能够被至少执行一次,操作覆盖是现代面向对象的,常用于替换过程语言中的语句和分支覆盖。

路径覆盖为程序中的执行路径排上编号,并一个一个的执行他们。很明显,在大型程序中,这样的编号是不确定的,测试者只能定义最关键最常用的路径,然后执行这些路径。

测试可以是手动进行也可以自动进行。在手动测试中,测试者需要与应用程序相互交互,首先启动程序,有条不紊的执行程序的功能,并观察执行结果。自动测试则是根据预先的定义的测试脚本然后实施执行步骤,测试脚本首先定义好每一步的测试行为和预期结果,实际应用中,用例和其他需求文档常常用于编写测试脚本。

手动测试最大的问题是在大多数实际情境中都是基于实时数据来执行的,对于手动测试中重复的执行部分,没有固定的预先定义的基准数据来保证相同的输出结果。因此,在自动测试的脚本中,预期的输出结果常常不会定义的很精确。测试的输出结果一般不会显示在屏幕上,而是储存在数据库中,这迫使测试者编写并允许SQL脚本或其他测试框架,来检查测试行动的结果。

对于准备、执行和管理方面,手动测试要花费很多代价,他们不能满足测试的要求量,而自动化测试使用工具来执行大量的测试,还不用人工参与。这些工具能够生成测试后的报表来帮助管理测试结果,自然地,需要由人来准备执行任务,还有编写测试脚本,安装测试环境等。

正如在图4中显示的那样,自动化测试可分为回归测试和运动测试。回归测试的意思是用相同的脚步重复的在相同的基线数据上进行测试,然后根据执行结果与上次测试结果做对比,观察是否不一致。测试的功能从表面上看起来都是不相关的。

回归测试由预定的测试脚本在设定的时间里自动的执行,在测试人员的测试中,测试人员的操作会被捕获工具程序记录到原始测试脚本中,回归测试是一种脚本的重复执行活动,在许多情况下,测试人员会修改记录捕获脚本来允许重复测试一些工具不能完成的功能。

运动测试也是一种自动的覆盖测试,运动测试工具能够自动和随机的生成很多测试方案,并能由用户执行测试,这种测试方式可类比用户随机按键,选择菜单或者点击任意按钮。工具生成的测试行为被记录在脚本中,这些脚本能够测试程序的功能,一旦程序有任何的错误或故障,都会记录在单独的脚步中,这些脚本叫做缺陷脚本,可用于重新定位错误然后找出原因。

由于回归测试和运动测试都是使用捕获工具,因此他们可以相互配合使用,然后创建一种很强大的自动化测试环境。在实践中,自动化测试的难点不是在实施上而是在稳定的测试环境(带有相同的数据库,相同的应用程序,网络速度,桌面环境,分辨率,颜色,字体等)中运行连续的程序脚本。所有的自动测试结束后,都应该能够清理环境,然后重建数据库和重新整理程序测试工具等。