软件工程

一、软件工程概述

1.1 软件的概念和特点

定义

程序

按事先设计的功能和性能需求执行的指令序列

数据

程序正常操纵信息的数据结构

文档

与程序开发、维护、使用有关的图文材料

特征

  • 软件是开发的或者是工程化的,并不是制造的
  • 软件生产是简单的拷贝
  • 软件会多次修改
  • 软件开发环境对产品影响较大
  • 软件开发时间和工作量难以估计
  • 软件的开发进度几乎没有客观衡量标准
  • 软件测试非常困难
  • 软件不会磨损和老化
  • 软件维护易产生新的问题

分类

按软件功能分为

  • 系统软件
  • 支撑软件
  • 应用软件

按服务对象分

  • 项目软件
  • 产品软件

发展

软件的发展过程大致可分为四个阶段。

从上世纪50年代中期到60年代中期,为个体化发展阶段,软件往往只是为解决某个实际问题而专门编写的程序,开发者即使用者。

从60年代中期到70年代中期,是作坊式发展阶段,早期软件作坊缺乏组织管理,程序编写结合了一定的说明。

从70年代中期到80年代的中期,是工程化发展的阶段,软件公司化运作,更加产品化、系列化、标准化、工程化,文档被引入软件的内涵。

从80年代中期到现在,软件的发展呈现产业化特点,市场更加广阔,品类更加丰富,产品生态链愈加完整。

1.2 软件危机的产生

软件危机的定义

在计算机软件的开发和维护过程中所遇到的一系列严重问题

  • 项目超出预算
  • 项目超过计划完成时间
  • 软件运行效率很低
  • 软件质量差
  • 软件通常不符合要求
  • 项目难以管理并且代码难以维护
  • 软件不能交付

软件危机的产生原因

客观:软件本身特点

  • 逻辑部件
  • 规模庞大

主观:不正确的开发方法

  • 忽视需求分析
  • 错误认为:软件开发=程序编写
  • 轻视软件维护

消除软件危机的途径

  • 对计算机软件有正确的认识:软件≠程序
  • 充分认识软件开发不是某种个体劳动的神秘技巧,而是组织良好、管理严密、个类人员协同配合、共同完成的工程项目
  • 推广使用在实践中总结出来的开发软件的成功技术和方法。开发和使用更好的软件工具

1.3 软件工程的概念和发展过程

软件工程的概念

IEEE 将软件工程定义为

  1. 应用系统化的、学科化的、定量的方法,来开发、运行和维护软件,即将工程应用到软件
  2. 对 1. 中各种方法的研究

目标

在给定的时间和预算中,按照用户需求,开发易修改、高效、可靠、可维护、适应力强、可移动、可重用的软件

软件工程三要素

  • 工具

    软件工程工具,为软件工程的过程和方法提供自动化或半自动化的工具支持。 将若干工具集成起来,与软件工程数据库和计算机系统构成一个支持软件开发的系统称“计算机辅助软件工程(CASE)”,系统中某一工具的信息加工结果可以作为另一工具的输入。集成的软件工程工具再加上人的因素构成了软件工程环境。比如建模工具Rational Rose、编程工具Visual Studio、测试工具LoadRunner等。

  • 方法

    软件工程方法,是完成软件工程项目的技术手段。它支持项目计划和估算、系统和软件需求分析、设计、编程、测试和维护。软件工程方法依赖一组原则,它贯穿软件工程的各个环节。软件工程方法主要分两类:结构化方法和面向对象方法。

  • 过程

    软件工程过程,贯穿软件开发的各个环节,在各环节之间建立里程碑。管理者在软件工程过程中对软件开发的质量、进度、成本进行评估、管理和控制;技术人员采用相应的方法和工具生成软件工程产品(模型、文档、数据、报告、表格等)。

软件工程发展过程

  1. 第一代——传统的软件工程
  2. 第二代——对象工程
  3. 第三代——过程工程
  4. 第四代——构件工程

image-20230220112014228

软件工程的七个原则

image-20230220112038835

1.4 软件工程知识体系与职业道德

软件工程的知识体系

image-20230220112121886

软件工程的误解

管理方的误解:

M1: 我们已经有一本关于软件生产的标准和过程的书,这还不能让我们学习到需要的知识吗?

R1: 相比最新的大型主机,工作站和PC,这会使我们在做高质量软件开发时花费更多时间。

M2: 如果我们项目进度落后了,可以加入更多的程序员来赶进度。

R2: 软件开发的机制和手工作业不一样。在一个延迟了的软件项目中加入新的开发人员只会让它延迟更多。

M3: 如果我们将软件项目外包给第三方,我们就轻松了,让那个公司去完成它吧。

R3: 如果组织管理方不懂得如何从内部管理和控制软件项目,即使将项目外包也无济于事。

客户方的误解

M1: 对目标的一般陈述就足以开始编程,我们可以今后再补充细节。

R1: 前期糟糕的项目需求定义,是导致软件失败的主要原因。

R2: 项目需求的确在不断变化,但变化所产生的影响是根据变化提出的时间不同而不同的。

开发人员: 软件从业者积累了50 年的编程文化。在早期的软件开发中,编程被视为一种艺术形式。

M1: 一旦我们编程完毕并成功运行,我们的工作就结束了。

R1: “越早开始写代码,我们就会花费越长的时间去完成它”。工业数据显示,软件开发60%-80%的精力将耗费在软件首次提交给用户以后。

M2: 当我的程序运行之前,我没有办法评估它的质量。

R2: 一个最有效的软件质量保证机制应当在项目的正式开始启动时——可以通过技术报告体现。

M3: 唯一可交付的工作成果是一个成功运行的项目程序。

R3: 一个可运行的程序只是软件结构的一部分,它还包含了许多其它因素。

M4: 软件工程将会让我们去创建大量不必要的文档,并且总是使我们的进度放慢。软件工程仅仅是文档而已。

R4: 软件工程并不是创建文档,而是创建质量。更好的质量减少返工的概率。更少返工会让项目更早交付。所有的文档都是提高团队沟通和质量所必须的。

职业道德和责任规范

image-20230220112154756

二、软件过程概念

2.1 软件生命周期

软件生命周期:软件产品或软件系统从设计、投入使用到被淘汰的全过程

image-20230220112431417

2.2 软件过程

软件过程:在工作产品构建过程中,所需完成的工作活动、动作和任务的集合

活动:主要指宽泛的目标,与应用领域、项目大小、结果复杂度或实施软件工程的重要程度没有直接关系

动作:包含主要工作产品生产过程中的一系列动作

任务:关注小而明确的目标,能够产生实际产品

2.3 软件过程模型

软件过程模型是软件开发全部过程、活动和任务的结构框架,它能直观表达软件开发全过程,明确规定要完成的主要活动、任务和开发策略。在软件过程模型框架的约束之下,软件开发才能够有序有效地进行,从而保证软件开发的成功。

软件过程模型也常被称为:软件开发模型、软件生存周期模型、软件工程范型。

2.4 能力成熟度模型

image-20230220112752504


瀑布模型

瀑布模型,英文称之为waterfall model,是第一个软件过程模型,也是极其重要的一个软件过程模型,由Winston Royce于1970年提出。瀑布模型规定了软件工程包括可行性研究、需求分析、总体设计、详细设计、编码、单元测试、系统测试、验收测试、运行与维护等活动,这些活动自上而下、相互衔接、次序固定,如同瀑布流水逐级下落,因此称为瀑布模型。由于瀑布模型规定的软件开发过程与软件生命周期一致,因此瀑布模型也称为经典生命周期模型。

  • 线性模型
  • 阶段间有顺序性和依赖性
  • 推迟实现的观点
  • 以文档为驱动

image-20230220112947300

缺点

  • 增加工作量
  • 早期错误发现晚
  • 开发风险大
  • 不适应需求变化

瀑布模型适用于系统需求明确且稳定、技术成熟、工程管理较严格的场合,如军工、航天、医疗。

V 模型

瀑布模型有一个变种,V模型。在V模型中,处于顶端的是编码,左侧是分析设计阶段,右侧是测试运维阶段。该模型将测试的各个阶段和分析设计的各个阶段关联起来,单元测试验证详细设计,系统测试验证总体设计,验收测试验证需求分析。

image-20230220113114541

原型模型

原型化的目的主要有两点:

  1. 明确并完善需求,通过演示原型实现,如图书借阅系统中的主要界面;
  2. 研究技术选择方案,通过技术验证原型实现,如智能家居系统中的部分监视和控制。

原型模型包括两个大阶段,原型构建阶段和系统开发阶段

image-20230220113250765

优点

  • 减少需求不明确带来的风险

缺点

  • 构造原型采用的技术和工具不一定主流

  • 快速建立起来的系统加上连续的修改可能导致原型质量低下

  • 设计者在质量和原型中进行折中

  • 客户意识不到一些质量问题

原型模型适用于客户定义一个总体目标集,但是他们并不清楚系统的具体输入输出;或开发者不确定算法的效率、软件与操作系统是否兼容以及客户与计算机交互的方式

增量模型

增量,它是满足用户需求的一个子集,能够完成一定功能、小而可用的软件。这里要注意区分增量和原型的异同。增量和原型都是系统的一部分,但是它们的构建原因和最终结局不同,原型构建是为了明确需求或验证方案,最终可能会被抛弃,而增量则是实际开发过程和最终系统的一部分

image-20230220113459930

  • 增量模型是一种非整体开发的模型,是一种进化式的开发过程
  • 增量模型从部分需求出发,先建立一个不完整的系统,通过测试运行这个系统取得经验和反馈,进一步使系统扩充和完善
  • 如此反复进行,直至软件人员和用户对所设计的软件系统满意为止
  • 增量模型结合了原型模型的基本要素和迭代的特征,采用了基于时间的线性序列,每个线性序列都会输出该软件的一个“增量”
  • 每个增量的开发可用瀑布或快速原型模型

优点

  • 增量概念的引入,使得不需要提供完整的需求,只要有一个增量出现,开发就可以进行,软件能够更早投入市场
  • 在项目初期,由于只开发部分系统,不需要投入太多的人力物力
  • 整个开发过程中,产品逐步交付,软件开发能够较好地适应需求的变化,同时能够看到软件中间产品,提出改进意见,减少返工,降低开发风险
  • 增量模型要求系统具有开放式体系结构,以便于增量的集成,同时也便于软件后期的维护

缺点

  • 每个增量必须提供一些系统功能,这使得开发者很难根据客户需求给出大小适合的增量

  • 其次,软件必须具备开放式体系结构,这在实践中往往是困难的

  • 如果不能进行良好的项目管理,采用增量模型的开发过程很容易退化成边做边改的方式,使软件过程控制失去整体性,从而导致软件开发失败。

增量模型适用于软件开发中需求可能发生变化、具有较大风险、或者希望尽早进入市场的项目

螺旋模型

螺旋模型提出将把开发活动和风险管理结合起来进行风险控制。螺旋模型最显著的特点就是在软件开发过程中加入风险管理。

image-20230220113754763

优点

  • 螺旋模型强调原型的可扩充性和可修改性,原型的进化贯穿整个软件生存周期,这将有助于目标软件的适应能力,支持用户需求的动态变化;

  • 原型可看作可执行的需求规格说明,易于为用户和开发人员共同理解,还可作为继续开发的基础,并为用户参与所有关键决策提供了方便;

  • 由于每个阶段都会进行风险分析和原型化验证,螺旋模型为项目管理人员及时调整管理决策提供了方便,进而可降低开发风险。

缺点

  • 如果每次迭代的效率不高,致使迭代次数过多,将会增加成本并推迟项目交付时间;

  • 使用该模型需要有相当丰富的风险评估经验和专门知识,要求开发队伍水平较高,否则会带来更大风险。

螺旋模型适用于需求不明确或者需求可能发生变化的大型复杂的软件系统。

支持面向过程、面向对象等多种软件开发方法,是一种具有广阔前景的模型。

喷泉模型

喷泉模型是一种以用户需求为动力,以对象为驱动的模型,主要用于描述面向对象的软件开发过程

  • 软件开发早期定义对象,整个开发过程充实和扩充对象

  • 各个阶段使用统一的概念和表示方法,生命周期各阶段无缝连接

  • 各个开发步骤多次反复迭代

image-20230220114025869

优点

喷泉模型的各个阶段没有明显的界限,开发人员可以同步进行开发,可以提高软件项目开发效率,节省开发时间,适应于面向对象的软件开发过程。

缺点

由于喷泉模型在各个开发阶段是重叠的,在开发过程中需要大量的开发人员,因此不利于项目的管理。

喷泉模型要求严格管理文档,使得审核的难度加大,尤其是面对可能随时加入的各种信息、需求与资料的情况。

喷泉模型只适用于面向对象开发

基于构件的开发模型

基于构件的开发模型是近年来得到广泛应用的软件过程模型。由于采用构件技术和重用技术,它改变了大型软件的开发方式,使得软件开发时考虑的焦点不再是实现,而是集成。通过复用和集成已有的构件来实现软件开发。构件是系统中模块化的、可更换的部分。构件是一个相对独立的模块,并且能够被另一个具有相同接口的构件所替换。构件实现特定的功能,并对实现进行封装,暴露一组接口,外界不需要知道构件内部实现的细节,只需要通过接口访问构件提供的服务。

image-20230220114153464

优点

  • 软件复用思想
  • 降低开发成本和风险,加快开发进度,提高软件质量

缺点

  • 模型复杂
  • 商业构件不能修改,会导致修改需求,进而导致系统不能完全符合客户需求
  • 无法完全控制所开发系统的演化
  • 项目划分的好坏直接影响项目结果的好坏

基于构件的开发模型适用于系统之间有共性的情况

统一过程模型

有着举足轻重的作用。统一过程模型是由Rational公司(现已被IBM收购)推出的完整且完美的软件工程方法,在面向对象领域获得了广泛应用。统一过程模型基于面向对象方法学,也就说,它适用于面向对象开发,开发过程中的需求分析和系统设计表示法均采用统一建模语言UML

统一过程模型从三个视角描述软件开发过程:动态视角,静态视角和实践视角。

  • 动态视角描述面向对象开发随时间变化的各个阶段,包括初始阶段、精化阶段、构建阶段和产品化阶段,采用迭代方式开发。

  • 静态视角描述在各个开发阶段所要进行的活动,如业务建模,需求,分析设计,实现,测试等。

  • 实践视角总结了在实际项目开发中建议采用的良好实践,这些实践经过大量实际项目证明,对提高软件开发效率和质量非常有效。

Rational统一过程完整且完美,适合大团队大项目。

image-20230220114408637

敏捷开发过程模型

敏捷开发强调高效工作、快速响应变化,具有敏捷性

敏捷软件过程是基本原理开发准则的结合

基本原理强调:

  • 客户满意度和较早的软件增量交付,软件开发采用迭代方式,每次迭代产生一个增量,每次交付的周期都很短;

  • 开发团队小但有激情,团队中的每一个人能力都很强,且工作非常有激情,这是保证快速开发的前提;

  • 开发采用非正式的方法,以可工作的软件为目标,适当时候进行结构调整和程序优化;

  • 每次迭代产生的增量都很小,保证每次迭代时间都很短,并且对变化具有敏捷性,能根据变化及时调整;

  • 整体开发过程尽量简单。

开发准则强调:

  • 分析和设计的交付

  • 开发者和客户之间积极持续的交流,客户会派工作人员到开发组,作为客户代表参与开发,使得交流及时和持续,保证敏捷性。

优点

  • 快速响应变化和不确定性
  • 可持续开发速度
  • 适应商业竞争环境下的有限资源和有限时间

缺点

  • 测试驱动开发可能导致通过测试但非用户期望

  • 重构而不降低质量困难

敏捷开发适用于需求模糊且经常改变的场合,适合商业竞争环境下的项目

如何选择软件过程模型

  1. 前期需求明确的情况下,尽量采用瀑布模型

  2. 用户无系统使用经验,需求分析人员技能不足的情况下,尽量借助原型模型

  3. 不确定因素很多,很多东西无法提前计划的情况下,尽量采用增量模型或螺旋模型

  4. 需求不稳定的情况下,尽量采用增量模型

  5. 资金和成本无法一次到位的情况下,可采用增量模型

  6. 对于完成多个独立功能开发的情况,可在需求分析阶段就进行功能并行,每个功能内部都尽量遵循瀑布模型

  7. 全新系统的开发必须在总体设计完成后再开始增量或并行

  8. 编码人员经验较少的情况下,尽量不要采用敏捷或迭代模型

  9. 增量、迭代和原型可以综合使用,但每一次增量或迭代都必须有明确的交付和出口原则

三、需求分析

3.1 需求分析的概念

定义

确定系统必须具有的功能和性能,系统要求的运行环境,并且预测系统发展的前景。

换句话说需求就是以一种清晰、简洁、一致且无二义性的方式,对一个待开发系统中各个有意义方面的陈述的一个集合。

3.2 需求的获取

定义

  • 软件需求的来源

  • 软件工程师收集这些软件需求的方法

需求类型

  • 功能性需求:描述系统应该做什么,即为用户和其它系统完成的功能、提供的服务。
  • 非功能性需求:必须遵循的标准,外部界面的细节,实现的约束条件,质量属性等等

也被称为需求抓取、需求发现和需求获得

3.3 需求分析/管理的过程

需求提炼定义

对应用问题及环境的理解和分析,为问题涉及的信息、功能及系统行为建立模型。将用户需求精确化、完全化,最终形成下一步的需求规格说明书

  • 需求提炼(需求分析)的核心在于建立分析模型。

  • 需求提炼(需求分析)采用多种形式描述需求,通过建立需求的多种视图,揭示出一些更深的问题。

  • 需求提炼(需求分析)还包括与客户的交流以澄清某些易混淆的问题,并明确哪些需求更为重要,其目的是确保所有风险承担者尽早地对项目达成共识并对将来的产品有个相同而清晰的认识。

需求规格说明书

软件需求规格说明书(SRS)——软件系统的需求规格说明,是对待开发系统的行为的完整描述。它包含了功能性需求和非功能性需求。

  • 需求分析工作完成的一个基本标志是形成了一份完整的、规范的需求规格说明书。

  • 需求规格说明书的编制是为了使用户和软件开发者双方对该软件的初始规定有一个共同的理解,使之成为整个开发工作的基础。

需求验证的重要性

如果在后续的开发或当系统投入使用时才发现需求文档中的错误,就会导致更大代价的返工。由需求问题而对系统做变更的成本比修改设计或代码错误的成本要大的多。

3.4 需求分析的任务

  • 建立分析模型:准确地定义未来系统的目标,确定为了满足用户的需求系统必须做什么。
  • 编写需求说明:用《需求规格说明书》规范的形式准确地表达用户的需求。

3.5 软件需求规格文档编制

软件需求规格说明的原则

  • 从现实中分离功能,即描述要“做什么”而不是“怎样实现”
  • 要求使用面向处理的规格说明语言(或称系统定义语言)
  • 如果被开发软件只是一个大系统中的一个元素,那么整个大系统也包括在规格说明的描述之中
  • 规格说明必须包括系统运行环境
  • 规格说明必须是一个认识模型
  • 规格说明必须是可操作的
  • 规格说明必须容许不完备性并允许扩充
  • 规格说明必须局部化和松散耦合

3.6 需求分析模型概述

  • 面向过程分析模型:其基本思想是用系统工程的思想和工程化的方法,根据用户至上的原则,自始自终按照结构化、模块化,自顶向下地对系统进行分析与设计。
  • 面向对象分析模型:由5个层次(主题层、对象类层、结构层、属性层和服务层)和5个活动(标识对象类、标识结构、定义主题、定义属性和定义服务)组成。

3.7 结构化分析方法

  • 面向数据流进行需求分析的方法

  • 结构化分析方法适合于数据处理类型软件的需求分析

  • 具体来说,结构化分析方法就是用抽象模型的概念,按照软件内部数据传递、变换的关系,自顶向下逐层分解,直到找到满足功能要求的所有可实现的软件为止

3.8 数据流图

image-20230220115805325

image-20230220115818882

  1. 加工

    表示对数据进行的操作, 如“处理选课单” 、“产生发票”等

    • 顶层的加工名就是整个系统项目的名字

    • 尽量最好使用动宾词组,也可用主谓词组

    • 不要使用空洞的动词

  2. 外部实体(数据源点/终点)

    • 位于系统之外的信息提供者或使用者,称为外部实体。即存在于系统之外的人员或组织。如“学务科”等

    • 说明数据输入的源点(数据源)或数据输出的终点(数据终点)

    • 起到更好的理解作用,但不是系统中的事物

  3. 数据流

    • 表示数据和数据流向, 由一组固定成分的数据组成 如“选课单”由“学号、姓名、课程编号、课程名”等成分组成
    • 数据流可从加工流向加工,也可在加工与数据存储或外部项之间流动;两个加工之间可有多股数据流
    • 用名词,不要使用意义空洞的名词
    • 尽量使用现实系统已有名字

image-20230220120133172

  1. 数据存储
    • 表示需要保存的数据流向, 如“ 学生档案”、“课程设置”等
    • 数据存储与加工的方向 “读出 ”、“写入 ”
    • 分层数据流程图中,数据存储一般局限在某一层或某几层
    • 命名方法与数据流相似

画数据流时需注意的问题

  1. 不要把控制流作为数据流

    image-20230220120225291

  2. 不要标出激发条件

    image-20230220120235367

几种错误

  1. 每个加工至少有一个输入数据流和一个输出数据流
  2. 数据流必须要么从某个加工流出、要么流入某个加工,而不能直接从外部项流向数据存储等等。

绘制步骤

  1. 绘制数据流图顶层:首先确定系统的输入和输出,画出顶层数据流图
  2. 绘制数据流图 1 层:从输入端开始,根据仓库业务工作流程,画出数据流流经的各加工框,逐步画到输出端,得到1层数据流图
  3. 绘制数据流图2层:加细每一个加工框
  4. 合成总体数据流图
  5. 检查与调整数据流图:在分析过程中,由于每个人的经验和思路不尽相同,对数据流图的分解方案可以有多种形式,不是唯一的。对每一张数据流图进行检查,如果太不均衡,就需要进行调整,尽量使分解后的各个软件子系统的复杂性得到均衡,便于今后设计工作的并行开展

3.9 数据流图的改进

  1. 检查正确性
    1. 数据守恒
    2. 数据存储的使用
    3. 父图和子图的平衡
  2. 提高易理解性
    1. 简化加工之间的联系:应尽量减少加工之间输入输出数据流的数目。因为加工之间的数据流越少,各个加工的功能就越相对独立
    2. 注意均匀分解
    3. 适当命名:名字的意义要明确,容易理解
  3. 重新分解:在画第N层时意识到在第N-1层或第N-2层所犯的错误,此时就需要对第N-1层、第N-2层作重新分解

3.10 编写数据字典

编写数据字典,写出系统需求规格说明书,提交审查,并编写测试验收计划、编写初步的用户手册概要。

3.11 什么是对象

在现实世界中有意义的、与所要解决的问题有关系的任何事物都可以作为对象,包括具体的物理实体的抽象、人为的概念、任何有明确边界和意义的东西。

3.12 面向对象的软件开发模型

  • 数据模型(对象模型):描述系统数据结构的对象模型

  • 行为模型(动态模型):描述系统控制结构

  • 功能模型:描述系统功能

一个典型的软件系统使用数据结构(对象模型),执行操作(动态模型),并且完成数据值的变化(功能模型)。

3.13 用例图

用例图的基本图形符号

用例建模用于描述系统需求,把系统当作黑盒,从用户的角度,描述系统的场景。主要图形元素有以下几个:

  • 参与者:是指外部用户或外部实体在系统中扮演的角色。可以是一个人、一个计算机子系统、硬件设备或者时间等角色image-20230220144436773

  • 用例:对一组动作序列的描述,系统通过执行这一组动作序列为参与者产生一个可观察的结果。用例名往往用动宾结构命名。image-20230220144441618

  • 执行关联: 参与者(Actor )执行用例(Use Case)之间的关系image-20230220144446024

用例图建模的过程

  1. 确定谁会直接使用该系统。这些都是参与者(Actor)。

  2. 选取其中一个参与者。

  3. 定义该参与者希望系统做什么,参与者希望系统做的每件事成为一个用例。

  4. 对每件事来说,何时参与者会使用系统,通常会发生什么,这就是用例的基本过程。

  5. 描述该用例的基本过程。

  6. 考虑一些可变情况,把他们创建为扩展用例。

  7. 复审不同用例的描述,找出其中的相同点,抽出相同点作为共同的用例。

  8. 重复步骤2~7找出每一个用例。

参与者

参与者(actor)是指系统以外的、需要使用系统或与系统交互的东西,包括人、设备、外部系统等。

参与者的三种表示形式

image-20230220144559747

用例

对一组动作序列的描述,系统通过执行这一组动作序列为参与者产生一个可观察的结果

特征为

  • 说明了系统具有的一种行为模式
  • 说明了一个参与者与系统执行的一个相关的事件序列
  • 提供了一种获取系统需求的方法
  • 提供了一种与最终的用户和领域专家进行沟通的方法
  • 提供了一种测试系统的方法
  • 用椭圆形表示

系统和关联

  • 系统:用于界定系统功能范围,描述该系统功能的用例都置于其中,而描述外部实体的参与者都置于其外。

    image-20230220144751812

  • 关联:连接参与者和用例,表示参与者所代表的系统外部实体与该用例所描述的系统需求有关。

image-20230220144801893

用例拓展

image-20230220144845903

3.14 用例之间的关系

  1. 关联

    表示参与者与用例之间的通信,任何一方都可发送或接受消息。

    【箭头指向】:指向消息接收方

    image-20230220145010617

  2. 泛化

    就是通常理解的继承关系,子用例和父用例相似,但表现出更特别的行为;子用例将继承父用例的所有结构、行为和关系。子用例可以使用父用例的一段行为,也可以重载它。父用例通常是抽象的。

    用例之间的is a kind of 关系,表示用例之间的场景共享;Actor之间的 is a kind of关系,一般描述职责共享。

    【箭头指向】:指向父用例image-20230220144955056

  3. 包含

    包含关系用来把一个较复杂用例所表示的功能分解成较小的步骤。一个用例可以包含另外一个用例。

    【箭头指向】:指向分解出来的功能用例

    image-20230220145035753

  4. 拓展

    扩展关系是指用例功能的延伸,相当于为基础用例提供一个附加功能。由一个用例的扩展点可以扩展出另外一个用例。

    【箭头指向】:指向基础用例

    image-20230220145107107

包含和拓展的区别

  • 在扩展关系中,一个基本用例执行时,可以执行、也可以不执行扩展用例部分

  • 在包含关系中,在执行基本用例时,一定会执行包含用例部分

关系 功能 表示法
关联 参与者与其参与执行的用例之间的通信途径 image-20230220145300304
扩展 在基础用例上插入基础用例不能说明的扩展部分 image-20230220145331788
泛化 用例之间的一般和特殊关系,其中特殊用例继承了一般用例的特性并增加了新的特性 image-20230220145320388
包含 在基础用例上插入附加的行为,并且具有明确的描述 image-20230220145336456

image-20230220145407989

image-20230220145501554

四、软件设计

4.1 软件设计的概念

软件设计定义为软件系统或组件的架构、构件、接口和其他特性的定义过程及该过程的结果。

作为软件生命周期中的一个活动,软件设计是连接用户需求和软件技术的桥梁,通过它,主要从软件外部视角提出的需求分析才能被转化为软件内部的结构,并且它还要指导后续的软件编码工作。

可以把设计工程活动分为软件架构设计与软件详细设计两种,分别描述软件的概貌与细节。

值得注意的地方是,软件设计大部分的工作为分解设计,也就是将软件映射为各组件;而系列模式设计,可以帮助我们提高相似组件的可复用性。

与需求分析阶段建立分析模型一样,设计阶段也需要建立设计模型。以需求分析阶段建立的数据模型、功能模型和行为模型为输入,设计阶段会建立数据、架构、接口和组件方面的设计模型

设计模型的分类

  • 数据设计
  • 架构设计
  • 接口设计
  • 组件设计

好的设计方案的特点

  • 第一,正确的承上,也就是说正确传递分析模型的结果;
  • 第二,正确的启下,即是说对软件开发后续过程的进行是有帮助的,影响应该是正面的。
  • 第三,从实现的角度给软件一个完整的说明,通过设计方案能够准确的预期未来的产品形态。

设计的质量属性

  • 功能性,指的是软件的功能要完整,符合用户的预期。
  • 易用性,指的是软件要好用,界面对用户友好。可靠性,是指软件不易出错,运行稳定。
  • 性能,主要是指软件的吞吐率和响应时间等等,能运行而且运行流畅。
  • 可支持性,又包含三个属性:扩展性、适应性和可维护性。
    • 扩展性是指软件添加新的功能或升级已有功能是否方便;
    • 适应性是指软件适应新的环境、新的变化是否容易;
    • 可维护性是指程序代码是否易懂、软件维护期间的成本是否更小等等。

设计相关概念

  1. 抽象:“忽略具体的信息将不同事物看成相同事物的过程”,包括数据抽象和过程抽象

    • 数据抽象:描述数据对象的冠名数据集合
    • 过程抽象:具有明确和有限功能的指令序列
  2. 体系结构:软件的整体结构和这种结构为系统提供概念上完整性的方式,可以使用大量的一种或多种模型来表达

    • 结构模型
    • 框架模型
    • 动态模型
    • 过程模型
    • 功能模型
  3. 设计模式:在给定上下文环境中一类共同问题的共同解决方案,它能够为一类相似的问题提供一种共同的解决方案,减少重复求解的工作量

  4. 模块化:软件被划分为命名和功能相对独立的多个组件(通常称为模块),通过这些组件的集成来满足问题的需求

  5. 信息隐藏:模块定义和设计时应该保证模块内的信息不可以被不需要这些信息的其他模块访问

    • 抽象有助于定义构成软件的过程(或信息)实体。

    • 信息隐藏原则定义和隐藏了模块内的过程细节和模块内的本地数据结构。

    • 一旦实现了信息隐藏,减少了透明调用,那么模块内部的功能显然就相对独立了

  6. 功能独立:每个模块只负责需求中特定的子功能,并且从程序结构的其他部分看,该模块具有简单的接口

    • 易于开发:功能被划分,接口被简化
    • 易于维护(和测试):次生影响有限,错误传递减少,模块重用
    • 定性衡量标准包括
      • 内聚性:模块的功能相对强度
      • 耦合性:模块之间的相互依赖程度
      • 模块独立性强 = 高内聚低耦合
  7. 精化:逐步求精的过程

    • 抽象使设计师确定过程和数据,但不局限于底层细节
    • 精化有助于设计者在设计过程中揭示底层细节
  8. 重构:不改变组件功能和行为条件下,简化组件设计(或代码)的一种重组技术

    检查现有设计的冗余情况、未使用的设计元素、无效或不必要的算法、较差的构建方式或不恰当的数据结构,或任何其他可被更改从而优化设计的问题

数据设计

数据设计(有时也被称为数据架构)构建高层抽象(客户/用户的数据视图)的数据模型、信息模型

体系结构设计

  • 系统需要执行的函数功能组件集(比如数据库有哪些表、程序有哪些类),

  • 组件之间通信、协同和合作的连接器(比如如何让一个类从数据库里获取数据),

  • 组件集成构成系统的约束(比如集成之后不同层次的类能否随意访问),

  • 整体特性的语义模型分析。我们经常会基于一些成熟的体系结构框架来搭建自己的体系结构。

  • 部署设计

    部署设计也属于体系架构设计的内容。它需要全盘考虑先前设计方案与QoS需求,平衡取舍相关问题成本,以实现最佳解决方案。提前考虑软件的部署,也有助于提早发现环境对软件带来的约束,从而在设计阶段考虑相应的解决办法。

接口设计(含界面设计)

接口设计其实包含内部接口的设计与外部接口的设计两个方面。

  • 内部接口的设计主要是指内部模块之间进行通信的接口设计,一般会作为架构设计或组件设计的一部分同时进行;

  • 而外部接口包括人机接口以及系统与外部系统的接口。

组件设计

组件设计,分为面向过程与面向对象两种方法。

  • 面向过程的组件设计主要是指函数与模块等的设计内容
  • 面向对象的组件设计主要是指类与操作等的设计内容

4.2 面向过程的设计

  • 变换分析
  • 事务分析
  • 混合结构分析

结构化组件设计

组件级设计也称为过程设计、详细设计,位于数据设计、体系结构设计和接口设计完成之后

流程图

  • 利用各种方块图形、线条及箭头等符号来表达解决问题的步骤及进行的顺序;
  • 是算法的一种表示方式

优点

  • 所有流程一目了然,工作人员能掌握全局。
  • 更换人手时,按图索骥,容易上手。
  • 所有流程在绘制时,很容易发现疏失之处,可适时予以调整更正,使各项作业更为严谨。

image-20230220152925454

image-20230220152940477

盒图(N-S图)

image-20230220153025949

image-20230220153049712

PDL(程序设计语言)

  • PDL是一种用于描述功能模块的算法设计和加工细节的语言。称为程序设计语言。它是一种伪码。
  • 伪码的语法规则分为“外语法”和“内语法”。
  • PDL具有严格的关键字外语法,用于定义控制结构和数据结构,同时它的表示实际操作和条件的内语法又是灵活自由的,可使用自然语言的词汇。

判定表(决策表)

  • 判定表用于表示程序的静态逻辑
  • 在判定表中的条件部分给出所有的两分支判断的列表,动作部分给出相应的处理
  • 要求将程序流程图中的多分支判断都改成两分支判断

4.3 面向对象的设计

架构设计

架构设计的目的是要勾画出系统的总体结构,这项工作由经验丰富的架构设计师主持完成。

  1. 构造系统的物理模型
  2. 设计子系统
  3. 非功能需求设计

进一步细化用例

类:类是包含信息和影响信息行为的逻辑元素。类的符号是由三个格子的长方形组成,有时下面两个格子可以省略。

详细设计一个类

由构件工程师详细设计每个类的属性、方法和关系。

  1. 定义类的属性
  2. 定义类的操作
  3. 定义类之间的关系

UML 顺序图

  • 顺序图描述了对象之间传送消息的时间顺序,用来表示用例中的行为顺序。
  • 顺序图将交互关系表示为一个二维图。即在图形上,顺序图是一张表,其中显示的对象沿横轴排列,从左到右分布在图的顶部;而消息则沿纵轴按时间顺序排序。创建顺序图时,以能够使图尽量简洁为依据布局

对象:顺序图中对象的符号和对象图中对象所用的符号一样。

image-20230220172121557

面向对象设计与结构化设计的过程和方法完全不同,要设计出高质量的软件系统,记住:

  • 对接口进行设计

  • 发现变化并且封装它

  • 先考虑聚合然后考虑继承

类内聚——设计类的原则是一个类的属性和操作全部都是完成某个任务所必须的,其中不包括无用的属性和操作

在面向对象设计中,耦合主要指不同对象之间相互关联的程度。如果一个对象过多地依赖于其它对象来完成自己的工作,则不仅使该对象的可理解性下降,而且还会增加测试、修改的难度,同时降低了类的可重用性和可移植性。

  • 交互耦合:

    如果对象之间的耦合是通过消息连接来实现的,则这种耦合就是交互耦合。在设计时应该尽量减少对象之间发送的消息数和消息中的参数个数,降低消息连接的复杂程度。

  • 继承耦合

    继承耦合是一般化类与特殊化类之间的一种关联形式,设计时应该适当使用这种耦合。在设计时要特别认真分析一般化类与特殊化类之间继承关系,如果抽象层次不合理,可能会造成对特殊化类的修改影响到一般化类,使得系统的稳定性降低。另外,在设计时特殊化类应该尽可能多地继承和使用一般化类的属性和服务,充分利用继承的优势。

可重用性

软件重用是从设计阶段开始的,所有的设计工作都是为了使系统完成预期的任务,为了提高工作效率、减少错误、降低成本,就要充分考虑软件元素的重用性。重用性有两个方面的含义

  • 尽量使用已有的类,包括开发环境提供的类库和已有的相似的类;
  • 如果确实需要创建新类,则在设计这些新类时考虑将来的可重用性。

五、程序实现

5.1 程序设计语言

程序应该正确、有效、易理解、简单、自然、可拓展、可伸缩

程序设计语言是:人与计算机通信的最基本工具。

特点是:不同的语言适用于不同的应用

image-20230220173203720

发展历程

第一代:机器语言

第二代:汇编语言

第三代:高级程序设计语言

第四代:4GL

5.2 编程习惯

  • 提高可靠性

  • 减少失效性

  • 降低调试、维护成本

  • 可读性

  • 可运行

设计原则

  • 自顶向下
  • 逐步细化
  • 模块化

设计风格

  1. 基本要求
  2. 可读性要求
  3. 正确性与容错性要求
  4. 可移植性要求
  5. 输入输出要求
  6. 重用性要求

5.3 程序的效率

程序的效率:程序的执行速度及程序所需占用的存储空间。

效率是一个性能要求,应当在需求分析阶段给出。软件效率以需求为准,不应以人力所及为准。

影响因素

  • 算法
  • 存储
  • 输入输出

5.4 编码管理

版本管理的意义

  • 目的:标识、控制和追踪软件开发和实施过程中产生的各种软件产品版本。

常见版本命名规则

主版本号 . 子版本号 [. 修正版本号 [. 编译版本号 ]]

面向对象程序设计

  • 概念:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递

  • 含义:面向对象程序设计是以建立模型体现出来的抽象思维过程和面向对象的方法。

  • 方法:选择程序设计语言、类的实现、方法的实现、用户接口的实现等

六、软件质量保证

6.1 软件质量相关概念

质量控制QC

审查产品相关的各个方面质量的过程

质量保证QA

系统监测和评估工程的各个方面,最大限度提高质量最低标准

软件质量:明确表示是否符合功能和性能要求,明确地记载开发标准和所有专业开发软件的期望的隐性特点

软件质量保证(SQA):遵照一定的软件生产标准、过程和步骤对软件质量进行评估的活动。

  • 审查:评审既定标准是否得到遵守。如IEEE、ISO、GB/T等
  • 监督:对比文档中描述的执行和实际操作步骤,确保执行过程采取适当步骤和操作方式
  • 审计:确保开发过程使用了恰当的质量控制措施,以符合相应的标准或过程。

软件评审

一个过程或会议期间进行的软件产品的审核,由项目人员、管理人员,用户、客户、用户代表或其他有关各方对一个软件产品进行评论或批准

软件可靠性

是指在给定时间内,特定环境下软件无错运行的概率

6.2 软件测试策略

含义

  • 软件测试策略为软件开发人员、质量保证组织、和客户提供了一个路线图
  • 测试

要求

  • 灵活性:有足够的可塑性来应付所有的大软件系统
  • 严格:保证对项目进程进行合理的计划和跟踪管理

image-20230221213513311

  • 单元测试:主要目的是验证软件模块是否按详细设计的规格说明正确运行。
  • 集成测试:主要目的是检查多个模块间是否按概要设计说明的方式协同工作。
  • 系统测试:主要目的是验证整个系统是否满足需求规格说明。
  • 验收测试:从用户的角度检查系统是否满足合同中定义的需求,以及以确认产品是否能符合业务上的需要。

回归测试

指有选择地重新测试系统或其组件,以验证对软件的修改没有导致不希望出现的影响,以及系统或组件仍然符合其指定的需求。

回归测试可以在所有的测试级别执行,并应用于功能和非功能测试中。

软件测试策略基本步骤

  • 计划与准备阶段
  • 执行阶段
  • 返工与回归阶段

6.3 软件测试技术

单元测试:针对软件设计的最小单位 ─ 程序模块,进行正确性检验的测试工作。

测试内容

  • 模块接口
  • 局部数据结构
  • 边界条件
  • 出错处理
  • 独立路径

测试环境搭建

  • 模块并非独立程序,进行测试时,要考虑它和外界的联系,需用一些辅助模块去做相应模拟
  • 驱动模块:用来模拟被测试模块的上一级模块,相当于被测模块的主程序。
  • 桩模块:模拟被测试的模块所调用的模块,而不是软件产品的组成的部分。

image-20230221213940548

集成测试

  • 含义:将软件集成起来后进行测试。别名:子系统测试、组装测试、部件测试等。
  • 目的:检查诸如两个模块单独运行正常,但集成起来运行可能出现问题的情况。
  • 方法:自顶向下的集成方法、自底向上的集成方法、SMOKE方法

自顶向下的集成方法

  • 基本思想:该集成方式将模块按系统程序结构,沿控制层次自顶向下进行集成。
  • 优点:可以较早地验证主要的控制和判断点。按深度方向,可首先实现和验证一个完整的软件功能。
  • 缺点:是桩模块的开发量较大
  • 适用:
    • 控制结构清晰稳定;
    • 高层接口变化较小;
    • 底层接口未定义或经常可能被修改;
    • 接口控制组件具有较大的技术风险,
    • 需要尽早被验证;
    • 希望尽早能看到产品的系统功能行为。

自底向上的集成方法

  • 基本思想:从软件结构最底层的模块开始,按照接口依赖关系逐层向上集成进行测试。
  • 优点:每个模块调用其他底层模块都已经测试,不需要桩模块;
  • 缺点:必须编写驱动模块;缺陷的隔离和定位不如自顶向下。
  • 适用:
    • 底层接口比较稳定;
    • 高层接口变化比较频繁;
    • 底层组件较早被完成。

系统测试

  • 压力测试
  • 性能测试
  • 功能测试
  • 恢复测试
  • 安全测试
  • 配置测试
  • 兼容性测试
  • 文档测试
  • 易用性测试

测试用例(test case):是测试输入、执行条件、以及预期结果的集合,是为特定的目的开发的,例如执行特定的程序路径或验证与指定的需求相符合。

主要测试方法

  • 黑盒测试:忽略系统或组件的内部机制,仅关注于那些响应所选择的输入及相应执行条件的输出的测试形式
  • 白盒测试:考虑系统或组件的内部机制的测试形式
  • 灰盒测试:介于白盒测试与黑盒测试之间的一种测试,多用于集成测试阶段,不仅关注输出、输入的正确性,同时也关注程序内部的情况。

白盒测试

  • 对程序模块的所有独立的执行路径至少测试一次;
  • 对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次;
  • 在循环的边界和运行界限内执行循环体;
  • 测试内部数据结构的有效性等。

语句覆盖:就是设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次。

测试用例的设计格式如下 【输入的(A, B, X),输出的(A, B, X)】

为图例设计满足语句覆盖的测试用例是: 【(2, 0, 4),(2, 0, 3)】 

image-20230221215557202

分支覆盖:就是设计若干个测试用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次。分支覆盖又称为判定覆盖。

【(2, 0, 4),(2, 0, 3)】覆盖 ace【L1】

【(1, 1, 1),(1, 1, 1)】覆盖 abd【L2】

【(2, 1, 1),(2, 1, 2)】覆盖 abe【L3】 【(3, 0, 3),(3, 1, 1)】覆盖 acd【L4】

条件覆盖:设计若干个测试用例,运行被测程序,使得程序中每个判断的每个条件的可能取值至少执行一次。

image-20230221220201782

测试用例 覆盖条件 覆盖组合
【(2, 0, 4), (2, 0, 3)】 (L1) image-20230221220212819①, ⑤
【(2, 1, 1), (2, 1, 2)】 (L3) image-20230221220215724②, ⑥
【(1, 0, 3), (1, 0, 4)】 (L3) image-20230221220218475③, ⑦
【(1, 1, 1), (1, 1, 1)】 (L2) image-20230221220221508④, ⑧

控制流图覆盖测试:是将代码转变为控制流图(CFG),基于其进行测试的技术。

image-20230221220333652

结点:符号○ ,表示一个或多个无分支的PDL语句或源程序语句。

边:箭头,表示控制流的方向。

汇聚节点:在选择或多分支结构中,分支的汇聚处应有一个汇聚结点。

区域:边和结点圈定的区域。对区域计数时,图形外的区域也应记为一个区域。

结点覆盖:对图中的每个节点,至少要有一条测试路径访问该节点。显然,节点覆盖=语句覆盖

边覆盖:对图中每一个可到达的长度小于(无边图)等于1 的路径,中至少存在一条测试路径覆盖。显然,边覆盖包含节点覆盖,且边覆盖也可以实现分支覆盖。

路径覆盖测试:就是设计足够的测试用例,覆盖程序中所有可能的路径

基本路径测试:将覆盖的路径数压缩到一定限度内,程序中的循环体最多只执行一次。

程序的环路复杂性:程序基本路径集中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必需的测试用例数目的上界。

独立路径:从控制流图来看,一条独立路径是至少包含有一条在其它独立路径中从未有过的边的路径。

计算方法 为边数, 为点数

黑盒测试

  • 测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性
  • 只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明
  • 又叫做功能测试或数据驱动测试。

基本思想

  • 把所有可能的输入数据,即程序的输入域划分成若干部分,然后从每一部分中选取少数有代表性的数据做为测试用例。

测试步骤

  • 划分等价类

  • 选取测试用例

等价类:某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的。

  • 有效等价类:对于程序的规格说明来说,是合理的,有意义的输入数据构成的集合。
  • 无效等价类:对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合。

原则1: 如果输入条件规定了取值范围,或值的个数,则可以确立一个有效等价类和两个无效等价类。

image-20230221220927376

原则2:如果输入条件规定了输入值的集合,或者规定了“必须如何”的条件,这时可确立一个有效等价类和一个无效等价类。

image-20230221220953721

原则3:如果输入条件是一个布尔量,则可以确定一个有效等价类和一个无效等价类。

image-20230221221016565

原则4:如果规定了输入数据的一组值,而且要对每个输入值分别进行处理。可为每一个输入值 确立一个有效等价类,所有不允许的输入值集合为一个无效类。

image-20230221221039606

原则5:如果规定了输入数据必须遵守的规则,则可以确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。

image-20230221221056932

等价类划分步骤

  1. 确定等价类
  2. 建立等价类表,列出所有划分出的等价类
  3. 为每一个等价类规定一个唯一编号;
  4. 设计一个新的测试用例,尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止;
  5. 设计一个新的测试用例,仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止

在某一PASCAL语言版本中规定:“标识符是由字母开头,后跟字母或数字的任意组合构成。有效字符数为不超过8个。”

并且规定:“标识符必须先说明,再使用。” “在同一说明语句中,标识符至少必须有一个。”

输入条件 有效等价类 无效等价类
标识符个数 ≥1个 (1) 0个 (2)
标识符字符数 8个 (3) 0个 (4);>8个 (5)
标识符组成 字母、数字的任意组合 (6); 非字母数字字符 (7);保留字 (8)
第一个字符 字母 (9) 非字母 (10)
标识符使用 先说明后使用 (11) 未说明已使用 (12)

image-20230221221325093

image-20230221221333762

七、软件维护

7.1 软件维护的概念和分类

IEEE/EIA 12207[ISO/IEC2008]中对软件维护的定义是:软件维护是指由于软件产品出现问题或需要改进而对代码及相关文档的修改,其目的是对现有软件产品进行修改的同时保持其完整性。

7.2 软件维护应注意的问题

  • 管理方面
  • 技术方面
  • 维护费用估算

7.3 软件维护技术

  • 程序的理解
  • 软件再工程
  • 软件逆向工程

八、软件项目管理

8.1 软件项目管理概念

软件项目管理的定义

  • 计划、协调、度量、监控、控制及报告等管理方法在软件开发和维护中的具体应用,以保证整个过程是系统的、有原则的、可量化的(IEEE610.12-90)。
  • 软件项目管理是为了使软件项目能够按照预定的成本、进度、质量顺利完成,而对人员(People)、产品(Product)、过程(Process)和项目(Project)进行分析和管理的活动。

软件项目管理的4P要素

  • 人员:招聘、选拔、绩效管理、培训、薪酬、职业发展、组织和工作设计、团队/文化的发展
  • 过程:软件过程提供一个框架,在此框架下可以制定项目开发的综合计划。
  • 产品:策划一个项目以前,应当建立产品的目标和范围,考虑可选的解决方案
  • 项目:理解成功项目管理的关键因素,掌握项目计划、监控和控制的一般方法

8.2 软件度量概念及面向规模的度量

软件度量的目的

软件项目管理的成熟化也需要度量与数字化,目的是持续改进软件过程,并用于项目估算、质量控制、生产率评估等。

软件度量的内容

软件度量的内容主要包括两个方面

一方面是对软件生产率的度量,这包括对项目工作量、项目周期、项目成本等方面的度量,

另一方面是对软件质量的度量,比如产品发布之前发现的缺陷数、产品发布后用户报告的缺陷数、产品的运行速度、可存储的容量、一段时间内累积无效服务时间等

在项目的初期,根据经验对当前软件项目的工作量和时间进行估算,随着项目的进展,将实际花费的工作量和时间与最初估算的工作量和时间进行对比,用于监控与调整项目的进展。无论是生产率度量还是质量度量,由于软件是人脑的创造性工作,不是流水线上提前完全确定可知的作业时间和工作量,这要求我们在进行项目度量时要以行业及组织的历史数据作为软件项目度量的基础。

软件度量的方法

主要是

  • 面向规模的度量

  • 面向功能点的度量

还有

  • 面向对象的度量
  • 面向用例的度量

面向规模的度量

通过对质量和(或)生产率的测量进行规范化而得到的,这些测量是根据开发过的软件的规模得到的。

  • 千行代码( KLOC ): 这些代码指的是源代码,通过源代码的行数来直观度量一个软件程序有多大规模
  • 生产率(PM):PM = L / E, L表示代码总量(单位:KLOC),E表示软件工作量(单位:人月)
  • 每千行代码的平均成本( CKL ):CKL = S / L,S为软件项目总开销 , L表示代码总量(单位:KLOC)
  • 代码出错率(EQRl):EQRl = Ne / L,Ne表示代码出错的行数, L表示代码总量(单位:KLOC)
  • 文档与代码比(Dl):Dl = Pd / L,Pd表示文档页数, L表示代码总量(单位:KLOC)
项目 代码行数(KLOC) 工作量(人月) 成本 (万元) 缺陷代码行数 文档页数 人员
A 12.1 24 168 134 29 3
B 27.2 62 440 321 1224 5
C 20.2 43 314 256 1050 6

以项目A为例:

生产率(PM)= 12.1/24 = 0.51 每千行代码的平均成本( CKL )= 168/12.1=13.9 代码出错率(EQRl)=134/12.1= 11.1 文档与代码比(Dl)=29/12.1=2.4

优点

  • 简单易行,自然直观

缺点

  • 依赖于程序设计语言的表达能力和功能
  • 软件开发初期很难估算出最终软件的代码行数
  • 对精巧的软件项目不合适

8.3.面向功能的度量

面向功能度量的概念

面向功能的软件度量基本思想是用软件的功能表示软件的规模,软件包含的功能越多,软件的规模越大。

应用最广泛的是功能点(Function Point, FP)法,前面小节讲的面向规模的度量是以代码行作为度量软件规模的基本单元。

而功能点法以功能点作为度量软件规模的基本单元。由于是以功能点作为度量依据,这种方法容易在项目开发初期就可估算出 ,但和面向规模的度量类似,功能点计算仍然要基于经验公式。

以发生过的历史项目数据作为度量的参考。

功能点法计算公式

UFC (Unadjusted Function Component) : 未调整功能点计数, 5个信息量的“加权和” TCF (Technical Complexity Factor): 技术复杂度因子 Fi: 14个因素的“复杂性调节值” (i =1..14) 0.65, 0.01都是经验常数,现在由国际组织根据大量项目跟踪分析获得。

UFC 相关五类组件

  • 内部逻辑文件(ILF, Internal Logical Files ) 一个用户可识别的逻辑相关的数据组,它在应用程序边界内,由用户输入来维护 它可能是某个大型数据库的一部分或是一个独立的文件
  • 外部接口文件(EIF, External Interface Files) 一个用户可识别的逻辑相关的数据组,但只能被引用,且数据完全存于软件外部,由另一个应用程序进行维护 是机器可读的全部接口(如磁盘或磁带上的数据文件) 是另一个应用程序的内部逻辑文件
  • 外部输入(EI, External Input) 来自于软件外部的数据输入 控制信息(不更新ILF) / 业务逻辑信息(更新ILF) 可来自于一个数据输入屏幕或其他应用程序。
  • 外部输出(EO, External Output) 经过处理的数据,由程序内部输出到外部 从ILF、EIF中取出数据经过一定的组合、计算后得出的输出数据, 如生成报表, 派生数据, 可能更新ILF
  • 用户查询(EQ, External Query) 一个输入输出的组合过程,从一个或多个ILF、EIF中取出数据输出到程序外部 输入过程不更新ILF,输出过程不进行任何数据处理

image-20230221223350514

功能组件类型 简单 中等 复杂
外部输入数(EI) 3 4 6
外部输出数(EO) 4 5 7
外部查询表(EQ) 3 4 6
内部逻辑文件数(ILF) 7 10 15
外部接口文件数(EIF) 5 7 10

外部输入EI数×加权因子(简单=3,平均=4,复杂=6) 外部输出EO数×加权因子(简单=4,平均=5,复杂=7) 外部查询EQ数×加权因子(简单=3,平均=4,复杂=6) 内部逻辑文件ILF数×加权因子(简单=7,平均=10,复杂=15) 外部接口EIF数×加权因子(简单=5,平均=7,复杂=10)

UFC = 上述计算值的总和(加权和)

复杂性调节因素

1.系统需要可靠的备份和复原吗?

2.系统需要数据通信吗?

3.系统有分布处理功能吗?

4.性能很关键吗?

5.系统是否运行在既存的、高度实用化的操作系统环境中?

6.系统需要联机数据项吗?

7.联机数据项是否在多屏幕或多操作之间进行切换?

8.需要联机更新主文件吗?

9.输入、输出、查询和文件很复杂吗?

10.内部处理复杂吗?

11.代码需要被设计成可重用吗?

12.设计中需要包括转换和安装吗?

13.系统的设计支持不同组织的多次安装吗?

14.应用的设计方便用户修改和使用吗?

复杂性调节因素值Fi

0-没有影响

1-偶有影响

2-轻微影响

3-平均影响

4-较大影响

5-严重影响

面向功能的度量优缺点

优点

  • 与程序设计语言无关, 在开发前就可以估算出软件项目的规模

不足

  • 没有直接涉及算法的复杂度,不适合算法比较复杂的软件系统;
  • 功能点计算主要靠经验公式,主观因素比较多

8.4. 软件项目估算

软件项目估算概念

概念

项目启动之前,软件团队应该估算将要做的工作、所需要的资源、成本、从开始到完成的时间,也即是对这些内容进行预测

策略

项目度量方法为项目估算提供了依据与有效输入

尽量把估算推迟到项目的后期进行

根据已经完成的项目进行估算

三点期望值法

在基于问题的分解估算方法中,通过估计最大值、最小值、最可能值的加权平均值作为期望值来估算 例如:如果估计系统X规模的最大值为100KLOC,最小值为50KLOC,最可能值为60KLOC,则其估计期望规模为(100+4×60+50)/6 = 65KLOC

软件描述(CAD软件)

CAD图形软件可接受来自用户的二维和三维几何数据,用户通过界面与CAD软件进行交互,并控制它,该软件具有良好的人机界面设计的特征。所有的几何数据及其支持信息存放在数据库中。开发设计分析模块,以产生所需的输出,这些输出将显示在各种不同的图形化设备上。软件在设计中要考虑与外设进行交互并控制它们,包括鼠标、数字化仪、打印机等。

基于LOC的项目估算

估算出各个子系统的代码行,例如三维几何分析功能的代码行估算范围为: 乐观值a:4600 可能值m:6900 悲观值b:8600 估算值: e = (a + 4m + b)/6 = 6800

子系统 代码行
图形用户界面及其控制机制 2 300
二维几何分析 5 300
三维几何分析 6 800
数据库管理 3 350
计算机图形显示 4 950
外设控制(与打印机、扫描仪等的接口) 2 100
设计分析子系统 8 400
合计 33200

历史数据 平均生产率PM: 620 LOC/PM(620行代码/人月) 每个人月的成本 C = 8000¥ 估算项目成本和工作量 估算工作量 = 总代码行/PM= 33200/620=54人月 估算成本 = 估算工作量 ×每个人月的成本 = 54人月× 8000 = 432000¥

基于功能点的项目估算

信息域 乐观值 可能值 悲观值 估算计数 加权因子 FP计数
输入数 20 24 30 24 4 96
输出数 12 15 22 16 5 80
查询数 16 22 28 22 4 88
文件数 4 4 5 4 10 40
接口数 2 2 3 2 7 14
总计 318

image-20230221224057607

计算出FP的估算值 FP = (0.65 + 0.01×∑Fi)×CT = 372 历史数据 平均生产率 6.5 FP/PM 每个人月的成本 C = 8000¥(平均月薪) 估算成本和工作量 工作量 58人月 成本 457000¥

基于过程分解的项目估算

活动 客户沟通 策划 风险分析 工程 构造发布 客户评估 合计(人月)
任务→ 分析 设计 编码 测试
功能↓
UICF 0.5 2.5 0.4 5.0 n/a 8.4
2DGA 0.75 4.0 0.6 2.0 n/a 7.35
3DGA 0.5 4.0 1.0 3.0 n/a 8.5
CGDF 0.5 3.0 1.0 1.5 n/a 6.0
DBM 0.5 3.0 0.75 1.5 n/a 5.75
PCF 0.25 2.0 0.5 1.5 n/a 4.25
DAM 0.5 2.0 0.5 2.0 n/a 5.0
合计 0.25 0.25 0.25 3.5 20.50 4.5 16.5 46.0
工作量 1% 1% 1% 8% 45% 10% 36%

8.5. 基于经验的软件估算

基于回归分析的经验估算模型

通过对以往软件项目中搜集的数据进行回归分析而导出

E=A+B×(ev)C

其中A、B、C是经验常数,E是工作量(人月),ev是估算变量(LOC或功能点)

面向规模的回归分析经验估算模型

E=5.2×(KLOC)0.91 Walston-Felix模型

E=5.5+0.73×(KLOC)1.16 Bailey-Basili模型

E=3.2×(KLOC)1.05 Boehm简单模型

E=5.288×(KLOC)1.047 Doty模型,用于KLOC>9的情况

E=A+B×(ev)C

其中A、B、C是经验常数,E是工作量(人月),ev是估算变量(LOC或功能点)

面向功能点的回归分析经验估算模型

E=-91.4+0.355FP Albrecht和Gaffney模型

E=-37+0.96FP Kemerer模型

E=-12.88+0.405FP 小型项目回归模型

基本COCOMO模型公式及计算方法

COCOMO是指COnstructive COst MOdel,构造性成本模型,Boehm于1981年提出,用于对软件开发项目的规模、成本、进度等方面进行估算

COCOMO模型是一个综合经验模型,模型中的参数取值来自于经验值,并且综合了诸多的因素、比较全面的估算模型

在欧盟国家应用较为广泛

8.6 项目进度计划

项目进度计划概念

定义:对项目进行任务划分,定义任务之间的依赖关系,并进行时间估算和资源分配,确保以最佳的时间与成本输出满足质量要求的产品

价值

  • 有序、可控制地对软件项目进行管理
  • 确保员工保持高生产率
  • 及时交付软件产品
  • 降低软件开发成本
  • 提高客户满意度
  • 及时发布产品新版本

甘特图

  • 显示基本的任务信息
  • 定义并查看任务的工期、开始时间和结束时间
  • 定义并查看任务所分配的资源的信息
  • 可定义任务间的前后关系

image-20230221224547246

里程碑

  • 里程碑显示项目进展中的重大工作完成
  • 里程碑不同于活动:活动是需要消耗资源的,里程碑仅仅表示事件的标记

image-20230221224631661

8.7 WBS分解与任务网络图

定义 工作分解结构(Work Breakdown Structure, WBS)是将项目按照功能或过程进行逐层分解,直到划分为若干内容单一、便于组织管理的单项工作,最终形成的树形结构示意图。

作用

  • 相关成员可直观了解软件项目中的各项任务(活动)
  • 将项目分解为可管理的任务(活动)
  • 作为项目计划与跟踪的基础

image-20230221224814209

任务网格图

定义

任务网络图是项目所有任务(活动)及其之间逻辑关系(依赖关系)的一个图解表示,并从左到右来表示项目的时间顺序。

作用

  • 可以分解任务以及各项任务所需要耗费的时间及成本

  • 可以显式的描绘各个任务间的时序依赖关系

构成

任务网络图是一个有向权重网络图,一般用节点表示事件,弧表示任务(活动) ,弧上的权值表示任务(活动)耗费的时间

image-20230221224856796

8.8 关键路径

关键路径(critical path)

在任务网络图中,从项目开始到项目完成有许多条路径,路径上所有弧权重之和最大的路径(路径最长)叫关键路径。

非关键路径(noncritical path)

在整个任务网络图中非最长的路径都叫非关键路径。

image-20230221224932690

(a)此网络中有多少路径?

(b)每条路径的长度是多少?

(c) 哪一条是关键路径?

(d)完成项目的最短时间是多少?

答:

两条:ABCDFHI, ABCEGHI

ABCDFHI=19天, ABCEGHI=20天

ABCEGHI

20天

关键路径的意义

  • 关键路径上任何任务(活动)的延长都会导致整个项目周期的延长
  • 如果想缩短项目周期,就必须缩短关键路径的长度
  • 项目经理应该随时关注关键路径上任务(活动)的完成情况以及关键路径是否发生了变化
  • 对WBS中任务的串行与并行安排方式有指导意义

串并行组合方式可能比纯并行对人员安排更合理