软件工程是软件开发的指导思想、方法体系,这属于软件设计师需要掌握的核心内容。
(1)软件工程知识:软件生存周期与软件生存周期模型、软件开发方法、软件开发项目管理、 软件开发工具与软件开发环境。
(2)系统分析基础知识:系统分析的主要步骤、机构化分析方法。
(3)系统设计基础知识:概要设计与详细设计的基本任务、系统设计的基本原理、系统模块结 构设计、结构化设计方法、面向数据结构的设计方法、系统详细设计。
(4)系统实施基础知识:系统实施的基本内容、程序设计方法、程序设计的基本模块、系统测试、系统转换。
(5)系统运行和维护基础知识:系统可维护性的概念、系统维护的类型、系统评价的概念和类型
(6)软件质量管理基础知识:软件质量特性(ISO/IEC 9126软件质量模型)、软件质量保证、软件复杂性的概念及度量方法(McCabe度量法)、软件评审(设计质量评审、程序质量评审)、软件容错技术。
(7)软件过程改进基础知识:软件能力成熟度模型CMM、统一过程(UP)与极限编程(XP)的基本概念。
本章的考点主要集中以下方面:
在软件生命周期与开发模型中,主要考查UP(统一过程)、XP(敏捷方法)以及传统软件开发模型的特点。
在系统开发方法论中,主要考查数据流图绘制原则、内聚与耦合。
在软件测试中,主要考查测试的阶段、白盒测试、黑盒测试、McCabe环路复杂度。
在软件质量保证中,主要考查软件质量特性。
在软件过程改进中,主要考查CMM每个阶段的特点及关键过程域。
在项目管理中,主要考查项目管理相关基本概念、Pert图、风险管理。
目录
一、软件工程知识
1.开发生命周期模型
系统开发的生命周期是指一个系统历经计划、分析、设计、编程、测试、维护直至淘汰的整个过程。生命周期阶段的划分通常可以采用以下三种方法:
Boehm划分法:计划(问题定义、可行性研究)、开发(需求分析、总体设计、详细设计、编码、测试)、运行(维护)三大阶段。
国标(GB8566-1988)划分法:可行性研究与计划、需求分析、概念设计、详细设计、实现、组装测试、确认测试、使用和维护。并在《GB/T8566-1995信息技术——软件生存期过程》中定义了获取过程、供应过程、开发过程、运行过程、维护过程、管理过程、支持过程七个部分。
RUP划分法:分为初始、细化、构造、移交四个主要阶段。为了指导软件的开发,可以用不同的方式将软件生命周期中的所有开发活动组织起来,从而形 成不同的软件开发模型。
2.开发模型
软件开发模型是几乎每次考试都会考查的重要知识点,现在主要掌握各种开发模型的特点与其应用场合。
瀑布模型:严格遵循软件生命周期各阶段的固定顺序,一个阶段完成再进入另一个阶段。其优 点是:可以使过程比较规范化,有利于评审;缺点在于:过于理想,缺乏灵活性,容易产生需求偏 差。所以瀑布模型的应用场合为:需求明确的项目、二次开发项目以及与原型法配合使用。
快速原型模型:采用了一种动态定义需求的方法,通过快速地建立一个能够反映用户主要需求 的软件原型,让用户在计算机上使用它,了解其概要,再根据反馈的结果进行修改,因此能够充分 体现用户的参与和决策。原型化人员对原型的实施很重要,衡量他们的重要标准是能否从用户的模 糊描述中快速地获取实际的需求。所以快速原型模型很好的弥补了瀑布模型的缺陷,它适合于需求不够明确的目。
演化模型:也是一种原型化开发,但与快速原型不同的是,快速原型模型在获得真实需求时, 就将抛弃原型。而演化模型则不然,它将从初始的模型中逐渐演化为最终软件产品,是一种“渐进 式”原型法。其应用场合也是需求不明确的项目。
增量模型:它采用的是一种“递增式”模型,它将软件产品划分成为一系列的增量构件,分别进行设计、编码、集成和测试。相对于原型法而言,这种模型其实是从系统开发的另一个方面看待问题,原型法关注点是“制作一个原型”,而增量模型的关注点是“系统的功能模块不是一次完成的,而是一块一块开发,以增加的方式进行的”。在现实开发中,我们会发现,一个项目开发过程既用了原型模型也用了增量模型。所以增量模型仍有利于进行需求不明确的项目开发。
螺旋模型:结合了瀑布模型和演化模型的优点,最主要的特点在于加入了风险分析。它是由制定计划、风险分析、实施工程、客户评估这一循环组成的,它最初从概念项目开始第一个螺旋。
喷泉模型:主要用于描述面向对象的开发过程,最核心的特点是迭代。所有的开发活动没有明显的边界,允许各种开发活动交叉进行。
UP:既是一个统一的软件开发过程,是一个通用过程框架,可以应付种类广泛的软件系统、不同的应用领域、不同的组织类型、不同的性能水平和不同的项目规模。UP是基于构件的,这意味着利用它开发的软件系统是由构件构成的,构件之间通过定义良好的接口相互联系。在准备软件系统所有蓝图的时候,UP使用的是统一建模语言UML。与其他软件过程相比,UP具有三个显著的特点:用例驱动、以基本架构为中心、迭代和增量。
UP中的软件过程在时间上被分解为四个顺序的阶段,分别是初始阶段、细化阶段、构建阶段和交付阶段。每个阶段结束时都要安排一次技术评审,以确定这个阶段的目标是否已经满足。如果评审结果令人满意,就可以允许项目进入下一个阶段。
UP一般用于大型软件的开发。
敏捷开发:从敏捷开发一词的敏捷可以看出,该方法是一种轻量级的开发方法。这种开发方法 的主要思想是:传统的软件工程方法文档量太“重”了,现在需要进行减负,所以将不必要的文档都去掉,这就形成了敏捷开发。具体一点讲,敏捷方法包括:XP(极限编程)、自适应开发、水晶方法、特性驱动开发等。这些方法中,最著名的是XP方法(当然,XP方法最著名,并非因为方法本 身很好,而是提出该方法的人,是个牛人)。在XP方法中,提出了四大价值观:沟通、简单、反馈、勇气。五大原则:快速反馈、简单性假设、逐步修改、提倡更改、优质工作。十二个最佳实践:计划游戏、小型发布、隐喻、简单设计、测试先行、重构、结对编程、集体代码所有制、持续集成、每周工作40小时、现场客户、编码标准。
二、系统开发方法论
系统开发方法包括:结构化方法、原型法、面向对象方法。其中原型法仅用于需求分析阶段。
1. 结构化方法
结构化方法是一种传统的软件开发方法,它是由结构化分析、结构化设计和结构化程序设计三 部分有机组合而成的。它的基本思想:把一个复杂问题的求解过程分阶段进行,而且这种分解是自 顶向下,逐层分解,使得每个阶段处理的问题都控制在人们容易理解和处理的范围内。
(1)结构化分析基础
结构化分析即我们平时所说的需求分析阶段,该阶段的主要任务是:解决“做什么”的问题。结构化分析方法是以自顶向下,逐步求精为基点,以一系列经过实践的考验被认为是正确的原以理论和技术为支撑,以数据流图,数据字典,结构化语言,判定表,判定树等图形表达为主要手段,强调开发方法的结构合理性和系统的结构合理性的软件分析方法。
(2)结构化设计基础
结构化设计是以结构化分析阶段所产生的成果为基础,进一步自顶而下、逐步求精和模块化的 过程。其主要工作内容是进行概要设计与详细设计(注:在结构化方法诞生时,架构设计还未提出,所以在此没有架构设计相关内容)。
概要设计的主要任务是把需求分析得到的数据流图转换为软件结构和数据结构。设计软件结构 的具体任务是:将一个复杂系统按功能进行模块划分、建立模块的层次结构及调用关系、确定模块 间的接口及人机界面等。数据结构设计包括数据特征的描述、确定数据的结构特性、以及数据库的 设计。显然,概要设计建立的是目标系统的逻辑模型,与计算机无关。在概要设计过程中常常会使 用结构图(包括模块、调用、数据)、层次图、HIPO(层次图加输入/处理/输出图)来描述程序的结构。
详细设计是对概要设计的一个细化,就是详细设计每个模块实现算法,所需的局部结构。经常 使用的工具包括程序流程图、盒图、PAD图(问题分析图)、PDL(伪码)。
(3)模块设计原则
使用结构化设计方法进行设计时,需要遵循一定的原则,总结起来主要是两个方面:信息隐蔽 与模块独立。
信息隐蔽指在设计和确定模块时,使得一个模块内包含信息(过程或数据),对于不需要这些 信息的其他模块来说,是不能访问的。这样做的好处是:让所有的操作都通过标准的接口进行,这 样避免了随意调用模块内部变量产生的混乱与错误。通过信息隐蔽可以提高软件的可修改性、可测 试性和可移植性。所以不仅在结构化方法中有信息隐蔽原则,在面向对象方法中,也有相应机制进 行信息隐蔽。
模块独立指每个模块完成一个相对独立的特定子功能,并且与其他模块之间的联系最简单。 保持模块的高度独立性,也是在设计时的一个很重要的原则。通常我们用耦合(模块之间联系的紧 密程度)和内聚(模块内部各元素之间联系的紧密程度)两个标准来衡量,我们的目标是高内聚、低耦合。
模块的内聚类型通常可以分为7种,根据内聚度从高到低排序如表 “模块的内聚类型“ 所示。
而此相对应,模块的耦合类型通常也分为7种,根据耦合度从低到高排序如表 “模块的耦合类型” 所示。
除了满足以上两大基本原则之外,通常在模块分解时还需要注意:保持模块的大小适中;尽可 能减少调用的深度;调用模块适中,即直接调用该模块的个数应该尽量大,但调用其他模块的个数则不宜过大;保证模块是单入口、单出口的;模块的作用域应该在之内;功能应该是可预测的。
2. 面向对象基本概念
面向对象开发方法与结构化开发有着本质的差异,这种方法引入了“对象”的概念,将数据和方法封装在一起,提高了模块的聚合度,降低了耦合度,更大程度上支持软件复用。是现在最流行 和最具有发展前景的软件开发方法。在了解该方法的具体内容之前,需要对面向对象的一系列概念 有所了解。
(1)对象
在计算机系统中,对象是指一组属性及这组属性上的专用操作的封装体,它由对象标识(名称)、属性(状态、数据、成员变量,也可以是另一个对象)和服务(操作、行为、方法)三个要 素组成。对象是系统中用来描述客观事物的一个实体,它们被封装为一个整体,以接口的形式对外提供服务。
(2)类
类是一组具有相同属性和方法的对象的集合。一个类中的每个对象都是这个类的一个实例(instance)。在系统分析和设计时,通常要把注意力集中在类上,而不是具体的对象上。每个类一般都有实例,没有实例的类是抽象类。抽象类不能被实例化(不能用new关键字去产生对象),抽象方法只需声明,而不需实现。是否建立了丰富的类库是衡量一个程序设计语言成熟与否的重要标志之一。
(3)继承与泛化
继承是面向对象方法中重要的概念,用来说明特殊类(子类)与一般类(父类)的关系,通常使用泛化来说明一般类与特殊类之间的关系,它们之间是一对多关系。
(4)封装
面向对象系统中的封装单位是对象,对象之间只能通过接口进行信息交流,对象外部不能对对象中的数据随意地进行访问。封装的目的是使对象的定义和实现分离,这样,就能减少耦合,类内部的实现可以自由改变而不会影响其他的类或对象。同时,类具有严密的接口保护,使对象的属性或服务不会随意地被使用,对象的状态易于控制,可靠性随之增强。
(5)多态性
多态(多种形式)性指一般类中定义的属性或服务被特殊类继承后,可以具有不同的数据类型或表现出不同的行为,通常是使用重载和改写两项技术来实现的。
(6)模板类
模板类也称为类属类,它用来实现参数多态机制。一个类属类是关于一组类的一个特性抽象,它强调的是这些类的成员特征中与具体类型无关的那些部分,而用变元来表示与具体类型有关的那 些部分。
(7)消息和消息通信
消息是向对象发出的服务请求,它通常包括提供服务的对象标识、消息名、输入信息和回答信息。消息通信则是面向对象方法学中的一个重要原则,它与对象的封装原则密不可分,为对象间提供了唯一合法的动态联系的途径。
2. 面向对象开发方法
面向对象开发方法更接近于人类的自然思维。人类在认识和理解现实世界中普遍运用的三个构 造法则是区分对象及其属性、区分整体对象及其组成部分、区分及形成不同对象类。而面向对象正 是基于对象及属性、类属及成员、整体及其部分这些概念基础之上的。因而它必然更容易被理解和 运用。面向对象的方法将对象的属性及服务视为一个整体。 这更符合客观世界的规律,从而使其理解与实现起来更加容易,进一步减少维护的费用。
面向对象开发方法的发展经历了一个漫长的周期,先后提出了多个不同的方法。这些方法中, 最有影响力的是:OMT方法、Coad/Yourdon方法、OOSE方法,而这些方法又进一步组合,形成了大家所熟知的UML。
正是由于有多种不同的方法,所以它们强调的重点与方法的特色也各有不同,因此这里我们只 对方法中具有代表性的或是都需要完成的一些内容进行论述。
(1)OOA
OOA即面向对象的分析,它的任务是了解问题域所涉及的对象、对象间的关系和操作,然后构造问题的对象模型。问题域是指一个包含现实世界事物与概念的领域,这些事物和概念与所设计的系统要解决的问题有关。在这个过程中,抽象是最本质和最重要的方法。针对不同的问题,可以选择不同的抽象层次,过简或过繁都会影响到对问题的本质属性的了解和解决。
(2)OOD
OOD即面向对象的设计,它在分析对象模型的基础上,设计各个对象、对象之间的关系(例如,层次关系、继承关系等)和通信方式(例如,消息模式)等,其主要作用是对OOA的结果作进一步的规范化整理,以便能够被OOP直接接受。
面向对象的设计需要遵循一系列的设计原则:
单一职责原则:设计目的单一的类;
开放-封闭原则:对扩展开放,对修改封闭;
李氏(Liskov)替换原则:子类可以替换父类;
依赖倒置原则:要依赖于抽象,而不是具体实现;针对接口编程,不要针对实现编程;
接口隔离原则:使用多个专门的接口比使用单一的总接口要好;
合重用原则:要尽量使用组合,而不是继承关系达到重用目的;
迪米特(Demeter)原则(最少知识法则):一个对象应当对其他对象有尽可能少的了解。
(3)OOP
OOP指系统功能的编码,实现在OOD阶段所规定的各个对象所应完成的任务。它包括每个对象的内部功能的实现,确立对象哪一些处理能力应在哪些类中进行描述,确定并实现系统的界面、输出的形式等。
三、软件测试与维护
1.软件测试基础
软件测试是在规定的条件下对程序进行操作,以发现程序错误,衡量软件品质,并对其是否能 满足设计要求进行评估的过程。测试的目的是发现尽可能多的缺陷。
为了让软件测试更有效率与效果,测试应遵循以下原则:
(1)尽早、不断的进行测试;
(2)程序员避免测试自己设计的程序;
(3)既要选择有效、合理的数据,也要选择无效、不合理的数据;
(4)修改后应进行回归测试;
(5)尚未发现的错误数量与该程序已发现错误数成正比。
2.测试阶段
软件测试按阶段划分,可分为:单元测试,集成测试,确认测试,系统测试。
(1)单元测试
单元测试,也称模块测试,通常可放在编程阶段,由程序员对自己编写的模块自行测试,检查 模块是否实现了详细设计说明书中规定的功能和算法。单元测试主要发现编程和详细设计中产生的 错误,单元测试计划应该在详细设计阶段制定。
单元测试期间着重从以下几个方面对模块进行测试:模块接口、局部数据结构、重要的执行通 路、出错处理通路、边界条件等。
(2)集成测试
集成测试,也称组装测试,它是对由各模块组装而成的程序进行测试,主要目标是发现模块间 的接口和通信问题。例如,数据穿过接口可能丢失;一个模块对另一个模块可能由于疏忽而造成有害影响;把子功能组合起来可能不产生预期的主功能;个别看来是可以接受的误差可能积累到不能接受的程度;全程数据结构可能有问题等。集成测试主要发现设计阶段产生的错误,集成测试计划应该在概要设计阶段制定。
集成的方式可分为非渐增式和渐增式。
非渐增式集成是先测试所有的模块,然后一下子把所有这些模块集成到一起,并把庞大的程序作为一个整体来测试。这种测试方法的出发点是可以“一步到位”,但测试者面对众多的错误现象,往往难以分清哪些是“真正的”错误,哪些是由其他错误引起的“假性错误”,诊断定位和改正错误也十分困难。非渐增式集成只适合一些非常小的软件。
渐增式集成是将单元测试和集成测试合并到一起,它根据模块结构图,按某种次序选一个尚未 测试的模块,把它同已经测试好的模块组合在一起进行测试,每次增加一个模块,直到所有模块被 集成在程序中。这种测试方法比较容易定位和改正错误,目前在进行集成测试时已普遍采用渐增式 集成。
(3)确认测试
确认测试(Validation Testing)主要依据软件需求说明书检查软件的功能、性能及其他特征是否与用户的需求一致。确认测试计划应该在需求分析阶段制定。
软件配置复查是确认测试的另一项重要内容。复查的目的是保证软件配置的所有成分都已齐全,质量符合要求,文档与程序完全一致,具有完成软件维护所必须的细节。
如果一个软件是为某个客户定制的,最后还要由该客户来实施验收测试(acceptance testing)便确认其所有需求是否都已得到满足。由于软件系统的复杂性,在实际工作中,验收测试可能会持续到用户实际使用该软件之后的相当长的一段时间。
如果一个软件是作为产品被许多客户使用的,不可能也没必要由每个客户进行验收测试。绝大 多数软件开发商都使用被称为α(Alpha)测试和β(Beta)测试的过程,来发现那些看起来只有最终用户才能发现的错误。
α测试由用户在开发者的场所进行,并且在开发者的指导下进行测试。开发者负责记录发现的错 误和使用中遇到的问题。也就是说,α测试是在“受控的”环境中进行的。
β测试是在一个或多个用户的现场由该软件的最终用户实施的,开发者通常不在现场,用户负责记录发现的错误和使用中遇到的问题并把这些问题报告给开发者。也就是说,β测试是在“非受控的”环境中进行的。
经过确认测试之后的软件通常就可以交付使用了。
(4)系统测试
系统测试的对象是完整的、集成的计算机系统,系统测试的目的是在真实系统工作环境下,验 证完整的软件配置项能否和系统正确连接,并满足系统/子系统设计文档和软件开发合同规定的要 求。系统测试的技术依据是用户需求或开发合同,除应满足一般测试的准入条件外,在进行系统测 试前,还应确认被测系统的所有配置项已通过测试,对需要固化运行的软件还应提供固件。
一般来说,系统测试的主要内容包括功能测试、健壮性测试、性能测试、用户界面测试、安全 性测试、安装与反安装测试等,其中,最重要的工作是进行功能测试与性能测试。功能测试主要采 用黑盒测试方法,性能测试主要验证软件系统在承担一定负载的情况下所表现出来的特性是否符合 客户的需要,主要指标有响应时间、吞吐量、并发用户数和资源利用率等。
3.白盒测试
白盒测试,又称透明盒测试、结构测试等,软件测试的主要方法之一。测试应用程序的内部结 构或运作,而不是测试应用程序的功能(即黑盒测试)。在白盒测试时,以编程语言的角度来设计 测试案例。测试者了解待测试程序的内部结构、算法等信息,这是从程序设计者的角度对程序进行 的测试。
白盒测试可以应用于单元测试、集成测试和系统的软件测试流程,可测试在集成过程中每一单元之间的路径,或者主系统跟子系统中的测试。
白盒测试主要是从覆盖源程序语句的详尽程度来分析。逻辑覆盖标准包括以下不同的覆盖标 准:语句覆盖、判定覆盖、条件覆盖、条件判定组合覆盖、多条件覆盖、路径覆盖。
语句覆盖:为了暴露程序中的错误,程序中的每条语句至少应该执行一次。该方法会选择足够 多的测试数据,使被测程序中每条语句至少执行一次。语句覆盖是很弱的逻辑覆盖。
判定覆盖:比语句覆盖稍强的覆盖标准是判定覆盖。判定覆盖的含义是:设计足够的测试用例,使得程序中的每个判定至少都获得一次“真值”或“假值”,或者说使得程序中的每一个 取“真”分支和取“假”分支至少经历一次,因此判定覆盖又称为分支覆盖。
条件覆盖:在设计程序中,一个判定语句是由多个条件组合而成的复合判定。为了更彻底地实 现逻辑覆盖,可以采用条件覆盖的标准。条件覆盖的含义是:构造一组测试用例,使得每一判定语 句中每个逻辑条件的可能值至少满足一次。
多条件覆盖:多条件覆盖也称条件组合覆盖,它的含义是:设计足够的测试用例,使得每个判 定中条件的各种可能组合都至少出现一次。显然满足多条件覆盖的测试用例是一定满足判定覆盖、 条件覆盖和条件判定组合覆盖的。
路径覆盖:最全面的覆盖。路径覆盖的含义是,选取足够的测试用例,使得程序的每条可能执 行到的路径都至少经过一次(如果程序中有环路,则要求每条环路径至少经过一次)。
4.McCabe复杂度
McCabe复杂度属于白盒测试技术。McCabe复杂度包括环路复杂度(Cyclomaticcomplexity)、基本复杂度、模块设计复杂度、设计复杂度和集成复杂度等。在软件设计师的考试中,要求掌握环路复杂度。
McCabe度量标准是将程序的流程图转化为有向图,也就是控制流图,然后以图论的知识和计算方法来衡量软件的质量。如图(a)对于应控制流程图是(b)。
程序流程图和对应的控制流图
将程序流程图转换成控制流程图以后,就可以计算其环路复杂度了。 计算有向图G的环路复杂度公式为:
V(G)=m-n+2
说明:其中V(G)是有向图G中的环路个数,m是G中的有向弧数,n是G中的节点数。
在图(b)中,有向弧数为15,结点数为12,所以环路复杂度为:15-12+2=5。
5.黑盒测试
黑盒测试也称功能测试,它是通过测试来检测每个功能是否都能正常使用。在测试中,把程序 看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测 试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据 而产生正确的输出信息。黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面 和软件功能进行测试。
常用的黑盒测试法包括:等价类划分、边值分析、错误推测和因果图。
(1)等价类划分
在设计测试用例时,等价类划分是用得最多的一种黑盒测试方法。所谓等价类就是某个输入域 的集合,对于一个等价类中的输入值来说,它们揭示程序中错误的作用是等效的。也就是说,如果 等价类中的一个输入数据能检测出一个错误,那么等价类中的其他输入数据也能检测出同一个错误;反之,如果等价类中的一个输入数据不能检测出某个错误,那么等价类中的其他输入数据也不 能检测出这一错误(除非这个等价类的某个子集还属于另一等价类)。
如果一个等价类内的数据是符合(软件需求说明书)要求的、合理的数据,则称这个等价类为 有效等价类。有效等价类主要用来检验软件是否实现了软件需求说明书中规定的功能。
如果一个等价类内的数据是不符合(软件需求说明书)要求的、不合理或非法的数据,则称这 个等价类为无效等价类。无效等价类主要用来检验软件的容错性。
黑盒测试中,利用等价类划分方法设计测试用例的步骤如下。
①根据软件的功能说明,对每一个输入条件确定若干个有效等价类和若干个无效等价类,并为 每个有效等价类和无效等价类编号。
②设计一个测试用例,使其覆盖尽可能多的尚未被覆盖的有效等价类。重复这一步,直至所有 的有效等价类均被覆盖。
③设计一个测试用例,使其覆盖一个尚未被覆盖的无效等价类。重复这一步,直至所有的无效 等价类均被覆盖。
应当特别注意,无效等价类用来测试非正常的输入数据,因此每个无效等价类都有可能查出软件中的错误,所以要为每个无效等价类设计一个测试用例。
(2)边值分析
经验表明,软件在处理边界情况时最容易出错。设计一些测试用例,使软件恰好运行在边界附近,暴露出软件错误的可能性会更大一些。通常,每一个等价类的边界,都应该着重测试,选取的测试数据应该恰好等于、稍小于或稍大于边界值。将等价类划分法和边值分析法结合使用,更有可能发现软件中的错误。
(3)错误推测
使用等价类划分和边值分析技术,有助于设计出具有代表性的、容易暴露软件错误的测试方案。但是,不同类型不同特征的软件通常又有一些特殊的容易出错的地方。错误推测法主要依靠测 试人员的经验和直觉,从各种可能的测试方案中选出一些最可能引起程序出错的方案。
(4)因果图
因果图法是根据输入条件与输出结果之间的因果关系来设计测试用例的,它首先检查输入条件的各种组合情况,并找出输出结果对输入条件的依赖关系,然后为每种输出条件的组合设计测试用例。
6.软件维护
软件维护主要是指根据需求变化或硬件环境的变化对应用程序进行部分或全部的修改。在修改 时应充分利用源程序,修改后应填写程序改登记表,并在程序变更通知书上写明新旧程序的不同之处。
软件维护是整个软件生命周期中最长的一个阶段,同时他也花费了整个软件生命周期中最多的 成本,20世纪80年代末用于软件维护的花费约为整个软件生命周期总花费的75%,而且还在逐年上升。
软件维护通常可分为以下四种类型:
改正性维护:是指改正在系统开发阶段已发生而系统测试阶尚未发现的错误。这方面的维护工 作量要占整个维护工作量的17%~21%。所发现的错误有的不太重要,不影响系统的正常运行,其维护工作可随时进行;而有的错误非常重要,甚至影响整个系统的正常运行,其维护工作必须制定计划,进行修改,并且要进行复查和控制。
适应性维护:是指使用软件适应信息技术变化和管理需求变化而进行的修改。这方面的维护工 作量占整个维护工作量的18%~25%。由于目前计算机硬件价格的不断下降,各类系统软件层出不穷,人们常常为改善系统硬件环境和运行环境而产生系统更新换代的需求;企业的外部市场环境和管理需求的不断变化也使得各级管理人员不断提出新的信息需求。这些因素都将导致适应性维护工作的产生。进行这方面的维护工作也要像系统开发一样,有计划、有步骤地进行。
完善性维护:这是为扩充功能和改善性能而进行的修改,主要是指对已有的软件系统增加一些 在系统分析和设计阶段中没有规定的功能与性能特征。这些功能对完善系统功能是非常必要的。另 外,还包括对处理效率和编写程序的改进,这方面的维护占整个维护工作的50%~60%,比重最大。
预防性维护:为了改进应用软件的可靠性和可维护性,为了适应未来的软硬件环境的变化,应 主动增加预防性的新的功能,以使应用系统适应各类变化而不被淘汰。例如:目前的网络带宽够用,但新系统一旦上线,将面临带宽不够的风险,此时进行带宽的扩容就是一种预防性维护。这方面的维护工作量占整个维护工作量的4%左右。
在软件维护这个主题中,另一个值得注意的方面是:软件的可维护性问题。软件的可维护性是 指理解、改正、改动、改进软件的难易程度。根据Boehm质量模型,通常影响软件可维护性的因素有可理解性、可测试性和可修改性。
(1)可理解性
可理解性是指维护人员理解软件的结构、接口、功能和内部过程的难易程度。
(2)可测试性
可测试性是指测试和诊断软件错误的难易程度。
(3)可修改性
可修改性是指修改软件的难易程度。
为了提高软件的可维护性,在软件生命周期的各个阶段都必须充分考虑维护问题。先进的软件工程方法是软件可维护的基础保证。
面向对象方法学的对象封闭机制、消息通信机制、继承机制和多态机制从根本上提高了软件的可理解性、可测试性和可修改性。
结构化设计的几条主要原则,如模块化、信息隐蔽、高内聚、低耦合等,对于提高软件的可理解性、可测试性和可修改性也都有重要的作用。
另外,书写详细正确的文档、书写源文件的内部注解、使用良好的编程语言、具有良好的程序设计风格,也有助于提高软件的可理解性。使用先进的测试工具、保存以前的测试过程和测试用例,则有助于提高软件的可测试性。
四、软件质量保证与软件过程改进
软件质量就是软件与显性与隐性需求相一致的程度。
软件质量保证,就是保证软件产品充分满足消费者要求的质量而进行的有计划、有组织的活动。它主要包括质量方针的制定和展开、质量保证方针和质量保证标准的制定、质量保证体系的建 立和管理、明确各阶段的质量保证工作、各阶段的质量评审、确保设计质量、重要质量问题的提出 与分析、总结实现阶段的质量保证活动、整理面向用户的文档和说明书、产品质量和质量保证系统 的鉴定、质量信息的收集分析及使用。而软件过程改进同样要靠标准作为指导方针,所以在本节将 介绍到很多与质量相关的标准。
1.软件质量特性标准
为了能够统一地描述软件质量特性,形成了许多质量特性标准,其中最常用的有国际通用的ISO/IEC 9126软件质量模型和McCall软件质量模型。
(1)IEO/IEC 9126模型
IEO/IEC9126模型是考试当中经常考查的一个知识点,考查方式主要是在选择题中,选出一个质量属性类中不属于(或属于)这一类的子特性,所以要求考生掌握此标准中的质量属性分类与其子特性。值得注意的是IEO/IEC9126模型等价于我国的国家标准《GB/T 16120—1996 软件产品评价、质量特性及其使用指南》。
(2)McCall质量模型
McCall质量模型从软件运行、软件修改和软件转移三个方面来考查软件的质量,其体系如图 “McCall质量模型体系表” 所示。
2.软件技术评审
正式的技术评审FTR(Formal Technical Review)是软件工程师组织的软件质量保证活动。它通常会采用系统化、严密的过程,包括制订计划、总体会议、做准备、开会、返工、追踪和因果分析。应培训审查者,依赖于缺陷检查表和其他错误分析技术;不是由作者来主持主审,而是由主持人陈述。
制订计划:确定谁参加,一般需要将人数控制在7人之内;确定准备哪些内容。 总体会议:确定评审的背景、假设及目标。
做准备:评审员预先阅读评审的材料。
评审会议:主持人引导,根据预先准备的检查表进行评审。返工:评审会议是为了发现问题,问题应在会后进行返工。跟踪:确定错误已经修改,并通知所有的评审人。
3.能力成熟度模型集成(CMMI)
能力成熟度模型集成融合了多种模型,形成了组织范围内过程改进的单一集成模型,其主要目 的是消除不同模型之间的不一致和重复,降低基于模型进行改进的成本。CMMI有两种表示法:阶段表示法和连续式表示法。这两种表示方法各有优缺点,均采用统一的24个过程域,它们在逻辑上是等价的,对同一个组织采用两种模型分别进行CMMI评估,得到的结论应该是相同的。但在考试时,往往涉及的是阶段表示法,所以在此仅对阶段表示法进行说明。
阶段式模型基本沿袭CMM模型框架,仍保持五个成熟等级,但关键过程域做了一些调整和扩充,如表 “过程域的阶段式分组” 所示。
当组织通过了某一等级过程域中的全部过程,即意味着该组织的成熟度达到了这一等级。利用 阶段式模型对组织进行成熟度度量,概念清晰、易于理解、便于操作。
五、软件项目管理
软件项目本身是复杂的,如果没有仔细地计划,复杂的项目是不可能成功的。一个计划良好的项目将受到有效的控制,进展明显,而参加该项目的人员都会得到支持以进行其工作。软件项目本 身也具有风险性,如果没有有效的风险管理也是不能成功的。
通常软件工程项目的管理比其他工程项目的管理更困难,这是因为:
软件产品不可见。开发的进度及产品的质量是否符合要求不明显,比较难进行把握。
没有标准的软件过程。尽管近几年来“软件过程改进”领域有许多进步,但由于团队、人员的个性化因素,还不存在一个放之四海皆真理的标准化软件过程。
大型软件项目常常是一次性项目。由于这些项目都是“前无古人”的,因此缺乏可以借鉴的历史经验。
这节主要包括网络计划技术中的一些计算问题以及项目管理相关的一些基本概念。
1. 项目管理九大知识领域
在PMBOK中提出了项目管理九大知识领域,此后这九大知识领域为业界普遍认同。九大知识领域中有四大核心领域:范围管理、时间管理、成本管理、质量管理,四大辅助领域:人力资源、沟通管理、风险管理、采购管理以及负责整体协调的整体管理。
整体管理:整体管理负责项目的全生命周期管理、全局性管理和综合性管理。全生命周期管理 意味着项目整体管理过程负责管理项目的启动阶段直到项目收尾阶段的整个项目生命周期。全局性 管理意味着项目整体管理过程负责管理项目的整体包括项目管理工作、技术工作和商务工作等。综 合性管理意味着项目整体管理过程负责管理项目的需求、范围、进度、成本质量、人力资源、沟通、风险和采购。
范围管理:范围管理确定在项目内包括什么工作和不包括什么工作,由此界定的项目范围在项 目的全生命周期内可能因种种原因而变化,项目范围管理也要管理项目范围的这种变化。
时间管理:时间管理又称进度管理,时间管理的职责是保证项目的所有工作都在一个指定的时 间内完成。
成本管理:成本管理就是要确保在批准的预算内完成项目。
质量管理:质量管理是指确定质量方针、目标和职责,并通过质量体系中的质量计划、质量控 制、质量保证和质量改进来使其实现的所有管理职能的全部活动。
人力资源管理:人力资源管理是为项目正常开展,而进行的招聘(选择)项目组人员并进行有 效组织、考核绩效支付报酬、进行有效激励、结合组织与个人需要进行有效开发以便实现最优组织绩效的全过程。
沟通管理:沟通管理是指项目组为项目干系人之间进行良好沟通而进行的管理活动。其内容包 括沟通计划编制、信息分发、绩效报告、项目干系人管理。
风险管理:所谓风险管理,就是要在风险成为影响项目成功的威胁之前,识别、着手处理并消 除风险的源头。
采购管理:采购管理是为完成项目工作,从项目团队外部购买或获取所需的产品、服务或成果 的过程。
2. 网络计划技术
用网络分析的方法编制的计划称为网络计划,它是一种编制大型工程项目进度计划的有效方法。计划借助于网络表示各项工作与所需要的时间,以及各项工作的相互关系。通过网络分析研究 工程费用与工期的关系,并找出在编制计划及计划执行过程中的关键路径,这种方法称为关键路径法(Critical Path Method,CPM)。还有一种方法,也是应用网络分析方法与网络计划,但它注重于对各项工作安排的评价和审查,这种方法称为计划评审技术(Program Evaluation and Review Technique,PERT) 。
(1)关键路径
在现代管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一项工程常被分为多个小的子工程,这些子工程被称为活动。在有向图中,若以顶点表示活动,弧表示活动之间的先 后关系,这样的图简称为AOV(Activity On Vertex)网;若以顶点表示事件,弧表示活动,权表示完成该活动所需的时间(称为活动历时或持续时间),这样的图称为AOE(Activity On Edge) 网。例如,图 “AOE网络的例子” 表示一个具有10个活动的某个工程的AOE网。图中有7个顶点,分别表示事件1~7,其中1表示工程开始状态,7表示工程结束状态。
因AOE网中的某些活动可以并行地进行,所以完成工程的最少时间是从开始顶点到结束顶点的最长路径长度,称从开始顶点到结束顶点的最长路径为关健路径(临界路径),关键路径上的活动为关键活动。
为了找出给定的AOE网络的关键活动,从而找出关键路径,先定义几个重要的量:
(1)Ve(j)、Vl(j):顶点j事件最早、最迟发生时间。
(2)e(i)、l(i):活动i最早、最迟开始时间。
从源点V1到某顶点Vj的最长路径长度,称为事件Vj的最早发生时间,记作Ve(j)。Ve(j)也是以Vj为起点的出边<Vj,Vk>所表示的活动ai的最早开始时间e(i)。
在不推迟整个工程完成的前提下,一个事件Vj允许的最迟发生时间,记作Vl(j)。显然,l(i)=Vl(j)-(ai所需时间),其中j为ai活动的终点。满足条件l(i)=e(i)的活动为关键活动,关键活动所组成的路径称 为关键路径。
求顶点Vj的Ve(j)和Vl(j)可按以下两步来做:
(1)由源点开始向汇点递推
其中,E1是网络中以Vj为终点的入边集合。
(2)由终点(汇点)开始向源点递推
其中,E2是网络中以Vj为起点的出边集合。
要求一个AOE网的关键路径,一般需要根据以上变量列出一张表格,逐个检查。例如,求图 “求关键路径的过程” 所示的AOE网的关键路径。
因此,图7-6的关键活动为a1,a2,a4,a8和a9,其对应的关键路径有两条,分别为V1→V2→V5→V7和V1→V4→V5→V7,长度都是10。
当然,上面所描述的方法用来求关键路径有一定的复杂度,需要进行大量的计算才能得到结果,这是一种严谨的方法,可以应对复杂的AOE网络图。,然而考试中涉及的图往往很简单,此时 再用这种方法来解决问题,会浪费不必要的时间,所以可以直接用“目测法“快速解决问题。所谓“目测法”,就是直接观察AOE网络中,从起点到终点,哪条路径最长,最长的那条路径,便是关键路径,而最长路径的长度,就是关键路径长度。
3. 甘特图
甘特图(Gantt图)用水平线段表示任务的工作阶段;线段的起点和终点分别对应着任务的开工时间和完成时间;线段的长度表示完成任务所需的时间。图 “甘特图” 给出了一个具有5个任务的甘特图。如果这5条线段分别代表完成任务的计划时间,则在横坐标方向附加一条可向右移动的纵线。它可随着项目的进展,指明已完成的任务(纵线扫过的)和有待完成的任务(纵线尚未扫过的)。我们从甘特图上可以很清楚地看出各子任务在时间上的对比关系。
在甘特图中,每一任务完成的标准,不是以能否继续下一阶段任务为标准,而是必须交付应交 付的文档与通过评审为标准。因此在甘特图中,文档编制与评审是软件开发进度的里程碑。甘特图 的优点是标明了各任务的计划进度和当前进度,能动态地反映软件开发进展情况。缺点是难以反映 多个任务之间存在的复杂的逻辑关系。
4. 风险管理
风险是指“损失或伤害的可能性”。所以风险包含这些特征:不确定性、针对未来、会带来损失。
项目风险管理通常包括风险识别、风险估计(风险评估)和风险驾驭(风险控制)三个主要活动。
风险识别的主要工作是找到潜在风险并将其文档化,它包括项目风险、技术风险和商业风险三种。
风险估计则是通过对各种风险发生的可能性和破坏性这两个方面进行评估,并将它们按优先级 进行排列。
风险驾驭则是指利用某种技术,如原型化、软件自动化、软件心理学、可靠性工程学等 方法设法避开风险。
当在软件工程环境中考虑风险时,主要是基于关心未来、关心变化、关心选择这三个概念提出 的。项目风险关系着项目计划的成败,而商业风险关系着软件的生存能力。在进行软件工程分析时,项目管理人员要进行四种风险评估活动,包括建立表示风险概率的尺度,描述风险引起的后果,估计风险影响的大小,确定风险估计的正确性。
在风险管理时,经常会应用风险曝光度(Risk Exposure)这个概念,它是计算方法是风险出现的概率乘以风险可能造成的损失。假设正在开发的软件项目可能存在一个未被发现的错误,而这个错误出现的概率是0.8%,给公司造成的损失将是2000000元,那么这个错误的风险曝光度就应为2000000×0.8%=16000元。