软件与软件工程介绍

软件的概念、特性和分类

  1. 软件的概念:软件是计算机系统中与硬件相互依存的另一部分,包括程序数据及其相关文档的完整集合

    • 程序:程序是按事先设计的功能和性能要求执行的指令序
列;

    • 数据:数据是使程序能够正确地处理信息的数据结构;

    • 相关文档:文档是与程序开发、维护和使用有关的图
文材料。

  2. 软件的特性

    形态特性、智能特性、开发特性、质量特性、生产特性、管理特性、环境特性、维护特性、废弃特性、应用特性

  3. 软件的分类

    系统软件、支撑软件(工具软件)、应用软件、可复用软件

软件危机

20世纪60年代,计算机已经应用在很多行业,解决问题的规模及难度逐渐增加,由于软件本身的特点及软件开发方法等多方面问题,软件的发展速度远远滞后于硬件的发展速度,不能满足社会日益增长的软件需求。软件开发周期长、成本高、质量差、维护困难,导致20世纪60 年代末软件危机的爆发。

除去软件本身的特点外,软件危机的原因还有以下几点:

  1. 缺乏软件开发的经验和有关软件开发数据的积累,使得开发工作的计划很难制定。
  2. 软件人员与用户的交流存在障碍,除了知识背景的差异,缺少合适的交流方法及需求描述工具也是一个重要的原因。
  3. 软件开发过程不规范,缺少方法论和规范的指导,开发人员各自为战。
  4. 随着软件规模的增大,其复杂性往往会呈指数级升高。
  5. 缺少有效的软件评测手段,提交用户的软件质量差。

软件工程

为了克服软件危机,1968年10月在北大西洋公约组织(NATO)召开的计算机科学会议上,Fritz Bauer首次提出“软件工程”的概念,试图将工程化方法应用于软件开发。

许多计算机和软件科学家尝试,把其他工程领域中行之有效的工程学知识运用到软件开发工作中来。经过不断实践和总结,最后得出一个结论:按工程化的原则和方法组织软件开发工作是有效的,是摆脱软件危机的一条主要的出路。

我国2006 年的国家标准GB/T11457—2006《软件工程术语》中对软件工程的定义为:
“应用计算机科学理论和技术以及工程管理原则和方法,按预算和进度,实现满足用户要求的
软件产品的定义、开发、发布和维护的工程或进行研究的学科。

概括地说,软件工程是指导软件开发维护的工程性学科,主要思想在于强调在软件开发过程中应用工程化原则的重要性。

  1. 软件工程的目标
    1. 软件的质量特性:功能性、可靠性、易用性、效率、维护性和可移植性。
    2. 软件工程的目标是运用先进的软件开发技术管理方法来提高软件的质量和生产率,也就是要以较短的周期、较低的成本生产出高质量的软件产品,并最终实现软件的工业化生产。
  2. 软件工程的基本原理
    • 用分阶段的生命周期计划严格管理
    • 坚持进行阶段评审
    • 实行严格的产品控制
    • 采用现代程序设计技术
    • 结果应能清楚地审查
    • 开发小组的人员应该少而精
    • 承认不断改进软件工程实践的必要性

软件生存期

概念:

软件也有一个孕育、诞生、成长、成熟和衰亡的生存过程,我们称这个过程为软件生命周期软件生存期

软件生存期又称软件生命周期,由软件定义软件开发运行维护三个时期组成。

  • 软件定义时期的主要任务是解决“做什么”的问题。
  • 软件开发时期的主要任务是解决“如何做”的问题。
  • 运行维护时期的主要任务是使软件持久地满足用户的需要。
graph TD
subgraph
软件生命周期 --> 软件定义
subgraph
软件定义 --> 问题定义
软件定义 --> 可行性研究
软件定义 --> 需求分析
end
软件生命周期 --> 软件开发
subgraph
软件开发 --> 概要设计
软件开发 --> 详细设计
软件开发 --> 编码
软件开发 --> 测试
end
软件生命周期 --> 运行维护
subgraph
运行维护 --> 改正性维护
运行维护 --> 适应性维护
运行维护 --> 完善性维护
运行维护 --> 预防性维护
end
end

各阶段耗时比例:

image-20231226210241938

软件定义

问题定义
  • 关键问题是:“要解决的问题是什么”。

  • 提交的内容为关于问题性质、工程目标和工程规模的书面报告。

可行性研究
  • 回答的关键问题是:“上一个阶段所确定的问题是否有行得通的解决办法”。

  • 提交的内容为可行性研究报告,即从技术、经济和社会因素等方面研究各方案的可行性。

需求分析
  • 对用户提出的要求进行分析并给出详细的定义。

  • 准确地回答“目标系统必须做什么”这个问题。也就是对目标系统提出完整、准确、清晰、具体的要求。

  • 编写软件需求说明书系统功能说明书初步的系统用户手册

  • 提交管理机构评审

软件开发

  • 任务:具体设计和实现前一个时期即软件定义时期定义的软件。
  • 执行人:系统设计员,高级程序员,程序员,测试工程师和辅助人员等
  • 阶段划分:分为概要设计、详细设计、编码和单元测试、集成测试和系统测试。其中前两个阶段又称为系统设计,后两个阶段又称为系统实现。
概要设计
  • 概括地回答“怎样实现目标系统?”。

  • 设计程序的体系结构,也就是确定程序由哪些模块组成以及模块间的关系。

  • 提交的文档是概要设计说明书。

详细设计
  • 回答“应该怎样具体地实现这个系统”。

  • 详细地设计每个模块,确定实现模块功能所需要的算法和数据结构。

  • 提交的文档是软件的详细设计说明书。

程序编码和单元测试
  • 写出正确的容易理解、容易维护的程序模块。

  • 提交的文档为源程序、详尽的程序说明和单元测试报告。

集成测试和系统测试
  • 通过各种类型的测试(及相应的调试)使软件达到预定的要求。

  • 提交的文档为测试计划、详细测试方案以及实际测试结果等。

运行维护

主要任务是使软件持久地满足用户的需要,通常有4类维护活动:

  • 改正性维护,也就是诊断和改正在使用过程中发现的软件错误;

  • 适应性维护,即修改软件以适应环境的变化;

  • 完善性维护,即根据用户的要求改进或扩充软件,使它更完善;

  • 预防性维护,即修改软件为将来的维护活动预先做准备。

典型文档

  • 软件需求规格说明书:描述将要开发的软件做什么。

  • 项目计划:描述将要完成的任务及其顺序,并估计所需要的时间及工作量。

  • 软件测试计划:描述如何测试软件,使之确保软件应实现规定的功能,并达到预期的性能。

  • 软件设计说明书:描述软件的结构,包括概要设计及详细设计。

  • 用户手册:描述如何使用软件。

软件工程化方法概论

通常把软件开发生命周期全过程中使用的一整套技术的集合称为方法学(methodology),也称为范型(paradigm)。在软件工程范畴中,这两个词的含义基本相同。

软件工程方法学包含三个要素:方法工具过程

  • 软件工程方法(method)为建造软件提供技术上的解决方法(“如何做”)。目前使用得最广泛的方法是传统方法(结构化方法)和面向对象的方法。
  • 工具为方法的运用提供自动的或半自动的软件支撑环境,如CASE(Computer Aided Soft-ware Engineering)工程
  • 过程是获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤

软件生存期模型

瀑布模型(文档驱动)

传统的瀑布模型

image-20231226211944358

特点

  1. 阶段间具有顺序性和依赖性。其中包含两重含义:
    1. 必须等前一阶段的工作完成之后,才能开始后一阶段的工作
    2. 前一阶段的输出文档就是后一阶段的输入文档
  2. 推迟实现的观点:
    1. 瀑布模型在编码之前设置了系统分析和系统设计的各个阶段,分析与设计阶段的基本任务规定,在这两个阶段主要考虑目标系统的逻辑模型,不涉及软件的物理实现。
    2. 清楚地区分逻辑设计与物理设计,尽可能推迟程序的物理实现,是按照瀑布模型开发软件的一条重要的指导思想。
  3. 质量保证的观点:
    1. 每个阶段都必须完成规定的文档,没有交出合格的文档就是没有完成该阶段的任务。
    2. 每个阶段结束前都要对所完成的文档进行评审,以便尽早发现问题,改正错误。

实际的瀑布模型

  • 实际的瀑布模型是“反馈环”的,如图所示。

  • 图中实线箭头表示开发过程,虚线箭头表示维护过程。

image-20231226212540631

优点

  • 可强迫开发人员采用规范化的方法。

  • 严格地规定了每个阶段必须提交的文档。

  • 要求每个阶段交出的所有产品都必须是经过验证的。

缺点

  • 由于瀑布模型几乎完全依赖于书面的规格说明,很可能导致最终开发出的软件产品不能真正满足用户的需要。如果需求规格说明与用户需求之间有差异,就会发生这种情况。

  • 瀑布模型只适用于项目开始时需求已确定的情况。

适用场景

  • 需求明确、较大型系统、开发周期不紧张

快速原型模型

快速原型是快速建立起来的可以在计算机上运行的程序,它所能完成的功能往往是最终产品能完成的功能的一个子集。

image-20231226214218092

分类

探索型原型

这种类型的原型是把原型用于开发的需求分析阶段,目的是要型清用户的需求,确定所期望的特性,并探索各种方案的可行性。它主要针对开发目标模糊,用户与开发都对项目都缺乏经验的情况,通过对原型的开发来明确用户的需求。

实验型原型

这种原型主要用于设计阶段,考核;实现方案是否合适,能否实陋。对于一个大型系统,若对设计方案心中没有把握时,可通过这种原型来证实设计方案的正确性

演化型原型

这种原型主要用于及早向用户提交一个原型系统,该原型系统或者包含系统的框架,或者包含系统的主要功能,在得到用户的认可后,将原型系统不断扩充演变为最终的软件系统。它将原型的思想扩展到软件开发的全过程。

优点

  • 有助于满足用户的真实需求。

  • 原型系统已经通过与用户的交互而得到验证,据此产生的规格说明文档能够正确地描述用户需求。

  • 软件产品的开发基本上是按线性顺序进行。

  • 因为规格说明文档正确地描述了用户需求,因此,在开发过程的后续阶段不会因为发现规格说明文档的错误而进行较大的返工。

  • 开发人员通过建立原型系统已经学到了许多东西,因此,在设计和编码阶段发生错误的可能性也比较小,这自然减少了在后续阶段需要改正前面阶段所犯错误的可能性。

  • 快速原型的突出特点是“快速”。开发人员应该尽可能快地建造出原型系统,以加速软件开发过程,节约软件开发成本。

原型的用途是获知用户的真正需求,一旦需求确定了,原型可以抛弃,当然也可以在原型的基础上进行开发。

缺点

  • 准确原型设计困难
  • 原型理解可能不同
  • 不利于开发人员创新

增量模型

  • 增量模型也称为渐增模型,是Mills等于1980年提出来的。

  • 使用增量模型开发软件时,把软件产品作为一系列的增量构件来设计、编码、集成和测试。

  • 每个构件由多个相互作用的模块构成,并且能够完成特定的功能。

image-20231226214519036

优点

  • 能在较短时间内向用户提交可完成一些有用的工作产品,即从第1个构件交付之日起,用户就能做一些有用的工作。
  • 逐步增加产品的功能可以使用户有较充裕的时间学习和适应新产品,从而减少一个全新的软件可能给用户组织带来的冲击。
  • 项目失败的风险较低,虽然在某些增量构件中可能遇到一些问题,但其他增量构件将能够成功地交付给客户。
  • 优先级最高的服务首先交付,然后再将其他增量构件逐次集成进来。因此,最重要的系统服务将接受最多的测试。

缺点

  • 增量构件划分以及集成困难
  • 容易退化为边做边改模型

螺旋模型(风险驱动)

在每个阶段之前都增加了风险分析过程的快速原型模型

image-20231227205233935

优点

  • 利于把软件质量作为软件的开发目标
  • 减少测试
  • 维护和开发不分开

缺点

  • 风险估计困难

迭代模型

敏捷开发方法与极限编程

敏捷开发:

  • 强调人与人之间的沟通。
  • 轻文档(弱化文档,但不是不需要文档)
  • 客户需要全程参与
  • 需求可以的变化

极限编程(Extreme Programming,XP):

  1. 用户故事(User Stories):以用户的视角描述软件功能和需求。
  2. 迭代开发:将开发过程划分为短小的迭代周期,并在每个周期内交付可用的软件。
  3. 快速反馈:通过频繁的客户反馈和自动化测试,及早发现和解决问题。
  4. 集体所有权(Collective Ownership):团队成员共同拥有代码和系统,鼓励共同协作和责任。
  5. 持续集成(Continuous Integration):团队成员频繁地将代码集成到共享代码库中,并进行自动化测试和构建。
  6. 可持续性(Sustainability):注重团队成员的健康、工作量的平衡和可持续的开发节奏。

敏捷原则

(1)我们最优先要做的是通过尽早、持续交付有价值的软件来使客户满意。

(2)即使在开发的后期,也欢迎需求变更。敏捷过程利用变更为客户创造竞争优势。

(3)经常交付可运行软件,交付的间隔可以从几个星期到几个月,交付的时间间隔越短越好。

(4)在整个项目开发期间,业务人员和开发人员必须天天都在一起工作。

(5)围绕有积极性的个人构建项目。给他们提供所需的环境和支持,并且信任他们能够完成工作。

(6)在团队内部,最富有效果和效率的信息传递方法是面对面交谈。

(7)可运行软件是进度的首要度量标准。

(8)敏捷过程提倡可持续的开发速度。责任人、开发者和用户应该能够保持一种长期、稳定的开发速度。

(9)不断地关注优秀的技能和好的设计会增强敏捷能力。

(10)简单是必要的。

(11)好的架构、需求和设计出自于自组织团队。

(12)每隔一定时间,团队会反省如何才能更有效地工作,并相应调整自己的行为。

CMM/CMMI

CMM

CMM(Capability Maturity Model for Software)软件能力成熟度模型。

  1.初始级(initial)

  工作无序,项目进行过程中常放弃当初的规划

  管理无章,缺乏健全的管理制度

  开发项目的成效不稳定,产品的性能和质量依赖于个人能力和行为。

  2.可重复级(Repeatable)

  管理制度化,建立了基本的管理制度和规程,管理工作有章可循

  初步实现标准化,开发工作较好的实施标准

  稳定课跟踪,新项目的计划和管理基于过去的实践经验,具有重复以前成功项目的环境和条件

  3.已定义级(Defined)

  开发的过程,包括技术工作和管理工作,均已实现标准化,文档化。

  建立了完善的培训制度和专家评审制度

  全部技术活动和管理活动均可稳定实施

  项目的质量,进度和费用均可控制。

  对项目进行中的过程,岗位和指责均有共同的理解。

  4.已管理级(Managed)

  产品和过程已建立了定量的质量目标。

  过程中活动的生产率和质量是可度量的。

  已建立过程数据库。

  已实现项目产品和过程的控制

  可预测过程和产品质量趋势。

  5.优化级(Optimizing)

  可集中精力改进过程,采用新技术,新方法。

  拥有防止出现缺陷,识别薄弱环节以及加以改进的手段

  可取得过程有效性的统计数据,并可据此进行分析,从而得到更佳方法。

CMMI

CMMI(Capability Maturity Model Integration)软件成熟度模型集成。CMMI是CMM模型的最新版本。

CMMI认证一共有5个级别,CMMI1级,初始级;CMMI2级,已管理级;CMMI3级,已定义级;CMMI4级,已量化管理级;CMMI5级,优化级

软件需求获取与结构化分析

需求获取的任务和原则

需求获取的任务

  1. 发现和分析问题,并分析问题的原因/结果关系。
  2. 与用户进行各种方式的交流,并使用调查研究方法收集信息。
  3. 按照三个成分观察问题的不同侧面、即数据、过程和接口
  4. 将获取的需求文档化,形式有用例、决策表、需求表等

需求获取的原则

  1. 深入浅出的原则。就是说,需求获取要尽可能全面、细致。获取的需求是个全集,目标系统真正实现的是个子集。
  2. 以流程为主线的原则。在与用户交流的过程中,应该用流程将所有的内容串起来。如信息、组织结构、处理规则等。这样便于交流沟通。流程的描述既有宏观描述,也有微观描述。

可以把软件需求分析阶段的工作分为4个步骤,即获取需求分析需求定义需求验证需求

  1. 需求获取

    通过启发、引导从客户(或用户)那里得到的原始需求是他们的业务要求(needs),简称为N。这是分析之前获取的需求,其中可能存在一些实际问题,这些问题只有通过分析才能得到解决,直接把获取的需求作为软件设计阶段的依据将会导致严重的后果。

  2. 分析需求

    认真研究获取的需求,必须考虑以下几方面:
    (1) 完整性:每项获取的需求都应给出清楚的描述,使得软件开发工作能够取得设计和实现该功能所需要的全部必要信息。
    (2) 正确性:获取的每项需求必须是准确无误的,并且需求描述无歧义性。
    (3) 合理性:各项需求之间、软件需求与系统需求之间应是协调一致的,不应存在矛盾和冲突。

    (4) 可行性:包括技术可行性 、经济可行性 、社会可行性 。
    (5) 充分性:获取的需求是否全面、周到。

    由于分析的过程会对获取的需求做部分调整,也即从获取的需求N中去掉了一些a,又补充了一些c,从而得到的是分析的需求R1(b+c)。

    image-20231229103820903

  3. 定义需求

    ​ 将已经过分析的需求清晰、全面、系统、准确地描述成为正式的文档,这一步定义需求的工作就是编写需求规格说明。

  4. 验证需求

    为了确保已定义的需求(需求规格说明)准确无误,并能为客户(或用户)理解和接受,需要对其进行严格的评审。


结构化分析方法

传统的分析建模方法称为结构化分析(structured analysis,SA)方法。

结构化分析方法是一种建模技术,它建立的分析模型如图所示。

image-20231229104334213

该模型的核心是数据字典,包括在目标系统中所使用和生成的所有数据对象。围绕这个核心有三种图

  1. 数据流图(DFD):描述数据在系统中如何被传送或变换,以及描述如何对数据流进行变换的功能(子功能),用于功能建模。
  2. 实体-关系图(ER图):描述数据对象及数据对象之间的关系,用于数据建模。
  3. 状态-迁移图(STD):描述系统对外部事件如何响应、如何动作,用于行为建模。

功能建模

功能建模的思想就是用抽象模型的概念,按照软件内部数据传递、变换的关系,自顶向下逐层分解,直到找到满足功能要求的所有可实现的软件为止。功能模型用数据流图来描述。

  1. 数据流图的基本图形符号

    image-20230912161513724

    多个数据流之间的关系

    image-20230912161752810

  2. 环境图

    环境图(context diagram)也称为顶层数据流图(或0层数据流图),它仅包括一个数据处理过程,也就是要开发的目标系统。环境图的作用是确定系统在其环境中的位置,通过确定系统的输人和输出与外部实体的关系确定其边界。

    image-20230912161909164

  3. 数据流图的分层

    稍为复杂一些的实际问题,在数据流图上常常出现十几个甚至几十个加工。这样的数据
,流图看起来不直观,不易理解。分层的数据流图能很好地解决这一向题。按照系统的层次结结构进行逐步分解,并以分层的数据流图反映这种结构关系,能清楚地表达整个系统,也容易
理解。

数据建模

  • 在结构化分析方法中,使用实体—关系建模技术来建立数据模型。
  • 这种技术是在较高的抽象层次(概念层)上对数据库结构进行建模的流行技术。
  • 实体—关系模型表示为可视化的实体—关系图(entity-relationship diagram,ERD),也称为ER图。
  • ER图中仅包含3种相互关联的元素:数据对象(实体)、描述数据对象的属性及数据对象彼此间相互连接的关系
数据对象
  • 数据对象是目标系统所需要的复合信息的表示,所谓复合信息是具有若干不同属性的信息。在ER图中用矩形表示数据对象。

  • 在实际问题中,数据对象(实体)可以是外部实体、事物、角色、行为或事件、组织单位、地点或结构等。

属性
  • 属性定义数据对象的特征,如数据对象学生的学号、姓名、性别、专业等,课程的课程编号、课程名称、学分等。

  • ER图中用椭圆或圆角矩形表示属性,并用无向边将属性与相关的数据对象连接在一起

关系
  • 不同数据对象的实例之间是有关联关系的,在ER图上用无向边表示。

  • 在无向边的两端应标识出关联实例的数量,也称为关联的重数

  • 从关联重数的角度可以将关联分为3种。

(1) 一对一(1:1)关联

(2) 一对多(1:m)关联

(3) 多对多(m:n)关联

  • 实例关联还有“必须”和“可选”之分。

​ 在ER图中用圆圈表示所关联的实例是可选的,隐含表示“0”,没有出现圆圈就意味着是必须的。出现在连线上的短竖线可以看成是“1”。

image-20231229140200301

行为建模

状态转换图(简称状态图)通过描绘系统的状态及引起系统状态转换的事件,来表示系统的行为。状态图中使用的主要符号如图所示。

image-20231229140308010

状态的表示:初态用实心圆表示,终态用牛眼图形表示,中间态用圆角矩形表示。

image-20231229140546665

决策表

决策树

结构化设计方法

软件设计的概念与原则

软件设计的原则

分而治之
模块独立性

模块独立性的度量准则

  • **耦合:**是模块之间的互相连接的紧密程度的度量。
  • **内聚:**是模块功能强度(一个模块内部各个元素彼此结合的紧密程度)的度量。
  • 模块独立性比较强的模块应是高内聚低耦合的模块。
image-20231229143221598

非直接耦合(Nondirect Coupling)

  • 两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。
  • 非直接耦合的模块独立性最强。

数据耦合(Data Coupling)

​ 一个模块访问另一个模型时,彼此之间是通过简单数据参数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息的。也是比较理想的耦合。

特征耦合(Stamp Coupling)

一组模块通过参数表传递记录信息,就是特征耦合。这个记录是某一数据结构的子结构,而不是简单变量。

控制耦合(Control Coupling)

如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能,就是控制耦合。

公共耦合(Common Coupling)

若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。

内容耦合(Content Coupling)

  • 一个模块直接访问另一个模块的内部数据
  • 一个模块不通过正常入口转到另一模块内部。
  • 两个模块有一部分程序代码重迭。(只可能出现在汇编语言中)。
  • 一个模块有多个入口。

image-20231230090303481

偶然内聚(Coincidental COhesion)

当模块内各部分之间没有联系,或者即使有联系,这种联系也很松散,则称这种模块为偶然内聚模块,内聚程度最低。

逻辑内聚(Logical Cohesion)

把几种相关的功能组合在一起,每次被调用时,由传送给模块的判定参数来确定该模块应执行哪个功能。

时间内聚(Classical Cohesion)

时间内聚模块大多为多功能模块,但模块的各个功能的执行与时间有关,通常要求所有功能必须在同一时间段内执行。

过程内聚(Procedural Cohesion)

如果一个模块内的处理是相关的,而且必须以特定次序执行,则是过程内聚。

顺序内聚

一个模块中的处理元素和同一功能密切相关,而且这些处理必须顺序执行,则称为顺序内聚。

功能内聚 (Functional Cohesion)

一个模块中各个部分都是完成某一具体功能必不可少的组成部分,或者说该模块中所有部分都是为了完成一项具体功能而协同工作,紧密联系,不可分割的。则称该模块为功能内聚模块。

提高抽象层次
  • 抽象是指忽视一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。
  • 当我们进行软件设计时,设计开始时应尽量提高软件的抽象层次,按抽象级别从高到低进行软件设计。
复用性设计
  • 复用是指同一事物不做修改或稍加修改就可以多次重复使用。将复用的思想用于软件开发,称为软件复用。
  • 我们将软件的重用部分称为软构件。
  • 也就是说,在构造新的软件系统时不必从零做起,可以直接使用已有的软构件即可组装(或加以合理修改)成新的系统。
灵活性设计

结构化设计

软件设计的任务

  • 从工程管理的角度,可以将软件设计分为概要设计阶段详细设计阶段
  • 从技术的角度,传统的结构化方法将软件设计划分为体系结构设计、数据设计、接口设计和过程设计4部分;
  • 面向对象方法则将软件设计划分为体系结构设计、类设计/数据设计、接口设计和构件级设计4部分。

image-20231230091024955

  • 体系结构设计:体系结构设计定义软件的主要结构元素及其之间的关系。

  • 接口设计:接口设计描述用户界面,软件和其他硬件设备、其他软件系统及使用人员的外部接口,以及各种构件之间的内部接口。

  • 数据设计:传统方法主要根据需求阶段所建立的实体—关系图(ER图)来确定软件涉及的文件系统的结构及数据库的表结构。

  • 过程设计:过程设计的主要工作是确定软件各个组成部分内的算法及内部数据结构,并选定某种过程的表达形式来描述各种算法。

体系结构设计

基于数据流方法的设计过程

程序流程图

标志符号

image-20240102154451072

McCabe度量法

环路复杂度:

V(G)= E - N + 2

E:边数

N:顶点数

面向对象方法与UML

面向对象=对象+类+继承+消息通信

UML简介

面向对象的建模语言很多,目前使用最广泛的是统一建模语言(UML,Unified Modeling Language);

特点:

  1. 统一标准

    UML不仅统一了Booch、OMT和OOSE等方法中的基本概念,还吸取了面向对象技术领域中其他流派的长处,其中也包括非OO方法的影响。已经成为OMG的标准。

  2. 面向对象

    UML支持面向对象技术的主要概念,它提供了一批基本的表示模型元素的图形和方法,能简洁明了地表达面向对象的各种概念和模型元素。

  3. 可视化,表达能力强

    UML是一种图形化语言,用UML的模型图形能清晰地表示系统的逻辑模型或实现模型。UML还提供了语言的扩展机制,用户可以根据需要增加定义自己的构造型、标记值和约束等。

  4. 独立于过程

    UML是系统建模的语言,不依赖特定的开发过程。

  5. 易于掌握使用

    UML概念明确,建模表示法简洁明了,图形结构清晰,容易掌握使用。

UML基本模型

image-20231230100856738

UML的事物

  • 事物是对模型中最具代表性成分的抽象,在UML中,可以分为结构事物、行为事物、分组事物注释事物4类。

image-20231230104253226

结构事物

  • 结构事物是UML模型的静态部分,主要用来描述概念的或物理的元素,包括类、主动类、接口、对象、用例、参与者、协作、构件和节点等。
  1. 类(class)── 类用带有类名、属性和操作的矩形框来表示。

    image-20231230101422858

    可见性:

    +: public

    -: private

    #: protected

    ~: package/default

  2. 主动类(active class)── 主动类的实例应具有一个或多个进程或线程,能够启动控制活动。

    image-20231230101541517
  3. 接口(interface)── 描述了一个类或构件的一组外部可用的服务(操作)集。

    接口定义的是一组操作的描述,而不是操作的实现。一般将接口画成从实现它的类或构件引出的圆圈,接口体现了使用与实现分离的原则。

    image-20231230101707479

  4. 对象(object)── 对象是类的实例,其名字下边加下划线,对象的属性值需明确给出。

    image-20231230101853215

  5. 用例(use case)── 也称用况,用于表示系统想要实现的行为,即描述一组动作序列(即场景)。而系统执行这组动作后将产生一个对特定参与者有价值的结果。

    image-20231230101921330

  6. 参与者(actor)── 也称角色,是指与系统有信息交互关系的人、软件系统或硬件设备,在图形上用简化的小木头人表示。

    image-20231230101948468

  7. 协作(collaboration)── 用例仅描述要实现的行为,不描述这些行为的实现。这种实现用协作描述。

    协作定义交互,描述一组角色实体和其他实体如何通过协同工作来完成一个功能或行为。类可以参与几个协作。

    image-20231230102052151

  8. 构件(component)── 也称组件,是系统中物理的、可替代的部件。它通常是描述一些逻辑元素的物理包。

    image-20231230102139964

  9. 节点(node)── 是在运行时存在的物理元素。它代表一种可计算的资源,通常具有一定的记忆能力和处理能力。

    image-20231230102149994

行为事物

  • 行为事物是UML模型的动态部分,包括两类:
  1. 交互(interaction)── 交互由在特定的上下文环境中共同完成一定任务的一组对象之间传递的消息组成。如图所示。交互涉及的元素包括消息、动作序列(由一个消息所引起的行为)和链(对象间的连接)。

    image-20231230102315130

  2. 状态机(state machine)── 描述了一个对象或一个交互在生存周期内响应事件所经历的状态序列,单个类或者一组类之间协作的行为都可以用状态机来描述。

    状态机涉及到状态、变迁和活动,其中状态用圆角矩形来表示。

    image-20231230102349995

分组事物

  • 分组事物是UML模型的组织部分。它的作用是为了降低模型复杂性。
  • UML中的分组事物是包(package)。
  • 包是把模型元素组织成组的机制,结构事物、行为事物甚至其他分组事物都可以放进包内。

image-20231230102455330

注释事物

  • 注释事物是UML模型的解释部分,它们用来描述和标注模型的任何元素。
  • 通常可以用注释修饰带有约束或者解释的图。

image-20231230102525238

UML的关系

image-20231230102748541

依赖关系

  • 依赖(Dependency)是两个事物之间的语义关系,其中一个事物发生变化会影响到另一个事物的语义,它用一个虚线箭头表示。
  • 虚线箭头的方向从源事物指向目标事物,表示源事物依赖于目标事物。

image-20231230105352997

关联关系

  • 关联(association)是一种结构关系,它描述了两个或多个类的实例之间的连接关系,是一种特殊的依赖。

  • 关联分为普通关联限定关联、关联类,以及聚合复合

  • 多重性(multiplicity):多重性表明在一个关联的两端连接的类实例个数的对应关系,即一端的类的多少个实例对象可以与另一端的类的一个实例相关。

    image-20240101102140470

聚合
  • 聚合(Aggregation)也称为聚集,是一种特殊的关联。它描述了整体和部分之间的结构关系。
  • 两种特殊的聚合关系:共享聚合(shared aggregation)和复合聚合(composition aggregation)。
  • 如果在聚合关系中处于部分方的实例可同时参与多个处于整体方实例的构成,则该聚合称为共享聚合。
  • 如果部分类完全隶属于整体类,部分类需要与整体类共存,一旦整体类不存在了,则部分类也会随之消失,或失去存在价值,则这种聚合称为复合聚合。

image-20240101102414333

泛化关系(继承)

泛化(generalization)关系就是一般类和特殊类之间的继承关系。在UML中,一般类亦称泛化类,特殊类亦称特化类。

实现关系(实现)

**实现(implement)**是泛化关系和依赖关系的结合,也是类之间的语义关系,通常在以下两种情况出现实现关系:

  1. 接口和实现它们的类或构件之间;
  2. 用例和实现它们的协作之间。

UML的图

image-20231230102828422

用例图

用例模型描述的是外部执行者(actor)所理解的系统功能。用例模型用于需求分析阶段,它的建立是系统开发者和用户反复讨论的结果,描述了开发者和用户对需求规格达成的共识。

四个元素:1. 系统 2. 参与者 3.用例 4. 关系

  • 主要参与者放左边,次要参与者放右边
  • 包含依赖一定执行,扩展依赖要满足一定条件执行
image-20231230123716222

关系类型

image-20231230115123877

6 分钟学会 UML 用例图_哔哩哔哩_bilibili

类图

类图描述类和类与类之间的静态关系,它是从静态角度表示系统的,因此类图属于一种静态模型。类图是构建其他图的基础,没有类图就没有状态图、协作图等其他图,也就无法表示系统其他方面的特性。

类图显示了类(及其接口)、类的内部结构以及与其他类的联系。联系是指类元之间的联系,在类的建模中可以使用关联、聚合和泛化(继承)关系。

关系:

image-20231230124956825

聚合(aggregation)关系:没有父类子类可以独立存在。

组合(composition)关系:没有父类子类无法存在。

交互图

顺序图(时序图、序列图)

顺序图描述对象之间的动态交互关系,着重表现对象间消息传递的时间顺序。

元素:角色(Actor)、对象(Object)、生命线(LifeLine)、控制焦点(Activation)、消息(Message)、自关联消息、组合片段

角色(Actor)
系统角色,可以是人或者其他系统,子系统。以一个小人图标表示。

对象(Object)
对象位于时序图的顶部,以一个矩形表示。对象的命名方式一般有三种:
1 对象名和类名。例如:华为手机:手机、loginServiceObject:LoginService。
2 只显示类名,不显示对象,即为一个匿名类。例如::手机、:LoginSservice。
3 只显示对象名,不显示类名。例如:华为手机:、loginServiceObject:。

生命线(LifeLine)
时序图中每个对象和底部中心都有一条垂直的虚线,这就是对象的生命线(对象的时间线)。以一条垂直的虚线表。

控制焦点(Activation)
控制焦点代表时序图中在对象时间线上某段时期执行的操作。以一个很窄的矩形表示。

消息(Message)
表现代表对象之间发送的信息。消息分为三种类型。

同步消息(Synchronous Message)
消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息的接收者放弃或者返回控制。用来表示同步的意义。以一条实线+实心箭头表示。

异步消息(Asynchronous Message)
消息发送者通过消息把信号传递给消息的接收者,然后继续自己的活动,不等待接受者返回消息或者控制。异步消息的接收者和发送者是并发工作的。以一条实线+大于号表示。

返回消息(Return Message)
返回消息表示从过程调用返回。以小于号+虚线表示。

自关联消息
表示方法的自身调用或者一个对象内的一个方法调用另外一个方法。以一个半闭合的长方形+下方实心剪头表示。

组合片段
组合片段用来解决交互执行的条件和方式,它允许在序列图中直接表示逻辑组件,用于通过指定条件或子进程的应用区域,为任何生命线的任何部分定义特殊条件和子进程。

img

通信图(协作图)

通信图是顺序图的一种变化形式,用于描述相互协作的对象间的交互关系和链接关系。

image-20240101114327644

状态图

状态图描述一个特定对象的所有可能的状态以及引起状态转换的事件。大多数面向对象技术都用状态图表示单个对象在其生命期中的行为。一个状态图包括一系列状态、事件以及状态之间的转移。

组成:状态、转换、事件

  • 状态:表示对象的生命周期的一种条件/情况,有初态和终态之分

img

  • 转换:两个状态之间的关系,它表明当某事发生时,对象先从当前状态转换到后来的状态,用带有标记事件的箭头表示。

    img

  • 事件:事件时引发变迁的消息,用箭头上的标记(事件表达式)表示。

活动图

活动图用来捕捉用例的活动,使用框图的方式显示动作及其结果。

活动图是一个流图,描述了从活动到活动的流。

它是另一种描述交互的方式,它描述采取何种动作,动作的结果是什么(动作状态改变),何时发生(动作序列),以及在何处发生(泳道)。

11. 面向对象——UML活动图(Activity Diagram) - 知乎 (zhihu.com)

3 分钟学会 UML 活动图_哔哩哔哩_bilibili

基本元素:1. 活动节点 2. 初始节点和终止节点 3. 转换 4.决策节点(空心菱型) 5.分叉与汇合(黑色粗线)

泳道图:按角色进行分组,流程的信息表达更加清晰准确。

构件图

构件图描述软件构件及构件之间的依赖关系,显示代码的静态结构。

构件是逻辑架构中定义的概念和功能(例如,类、对象及它们之间的关系)在物理架构中的实现。典型情况下,构件是开发环境中的实现文件。

软件构件分类:

  • 源构件:源构件仅在编译时才有意义。典型情况下,它是实现一个或多个类的源代码文件。
  • 二进制构件:典型情况下,二进制构件是对象代码,它是源构件的编译结果。
  • 可执行构件:可执行构件是一个可执行的程序文件,它是链接所有二进制构件所得到的结果。一个可执行构件代表在处理器(计算机)上运行的可执行单元。

部署图

部署图描述处理器、设备和连接,它显示系统硬件的物理拓扑结构及在此结构上执行的软件。
部署图可以显示计算节点的拓扑结构和通信路径、节点上运行的软件以及软件包含的逻辑单元。

image-20240101123138498

面向对象分析

面向对象分析概述

确定系统边界

系统边界是系统的所有内部成分与系统以外各种事物的分界线。系统只通过边界上有限数量的接口与外部的系统参与者(人员、组织、设备或外系统)进行交互。

image-20240101123643096

面向对象分析的3种模型

  • 用例模型:用例和场景表示的功能模型;
  • 对象模型:用类和对象表示的静态模型;
  • 交互模型:由状态图和顺序图表示的动态模型。

建立用例模型

过程

  1. 确定业务参与者──标识目标系统将支持的不同类型的用户,可以是人、事件或其他系统。
  2. 确定业务需求用例──参与者需要系统提供的完整功能。
  3. 创建用例图──标识参与者与用例之间、用例与用例之间的关系。

建立对象模型

对象模型的5个层次

Coad & Yourdon提出,复杂问题(大型系统)的对象模型应该由下述5个层次组成:

主题层(也称为范畴层)、类-对象层、结构层、属性层和服务层,如图所示。

image-20240101124901532

建立动态模型

在开发交互式系统时,动态模型起着很重要的作用。
在UML中动态模型的描述工具有顺序图、通信图和状态图。

软件体系结构与设计模式

设计模式

软件修养 – 一篇搞定设计原则和 23 种设计模式 | MakeOptim

创建型

工厂方法模式(Factory Method)

定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行

抽象工厂模式(Abstract Factory)

为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以从抽象工厂中选出相应的系列创建一个具体的工厂类,而无需指定它们的具体类

构造型

适配器模式(Adapter、Wrapper、Translator)

将某个类的接口转换成客户端期望的另一个接口表示。适配器模式可以消除由于接口不匹配所造成的类兼容性问题

行为型

观察者模式(Observer or Publish/subscribe)

在对象间定义一个一对多的联系性,由此当一个对象改变了状态,所有其他相关的对象会被通知并且自动刷新

黑板模式(Blackboard Design Pattern)

黑板模式(Blackboard Design Pattern)是观察者模式的一个扩展允许消息的读写同时进行,广泛地交互消息。

策略模式(Strategy)

定义一个算法的系列,将其各个分装,并且使他们有交互性。策略模式使得算法在用户使用的时候能独立的改变

面向对象设计

软件设计原则

Tags | MakeOptim

单一职责原则

单一职责原则(SRP:Single responsibility principle):一个类应该只有一个发生变化的原因,即一个类只负责一项职责

开闭原则

开闭原则(OCP :Open Closed Principle):软件中的实体(类,模块,函数等等)应该对扩展开放,对修改封闭,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为

里式替换原则

里氏替换原则(LSP:Liskov Substitution Principle):派生类(子类)对象可以在程序中代替其基类(超类)对象

依赖倒置原则

依赖倒置原则(DIP :Dependence Inversion Principle):

  • 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节
  • 细节应该依赖抽象

也就是说高层模块,低层模块,细节都应该依赖抽象

迪米特原则

迪米特法则(LOD:Law Of Demeter):又叫作最少知识原则(Least Knowledge Principle,LKP)。只与你的直接的朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性

接口隔离原则

接口隔离原则(ISP :Interface Segregation Principle):客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。

组合/聚合原则

组合/聚合复用原则(CARP:Composite/Aggregate Reuse Principle):在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,新对象通过向这些对象的委派达到复用已有功能的目的。就是说要尽量的使用合成和聚合,而不是继承关系达到复用的目的

简短表达就是:尽量使用组合/聚合,尽量不要使用继承

软件测试方法

软件测试的基本概念

什么是软件测试?

  • 软件测试是在软件投入生产性运行之前,对软件需求分析、设计规格说明和编码的最终复审,是软件质量控制的关键步骤。
  • 软件测试是为了发现错误而执行程序的过程。
  • 或者说,软件测试是根据软件开发各阶段的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结果),并利用这些测试用例去运行程序,以发现程序错误的过程。

软件测试的目的

​ 基于不同的立场,存在着两种完全不同的测试目的。

  • 从用户的角度出发,普遍希望通过软件测试检验软件中隐藏的错误和缺陷,以考虑是否可以接受该产品。
  • 从软件开发者的角度出发,则希望测试成为表明软件产品中不存在错误的过程,验证该软件已正确地实现了用户的要求,确立人们对软件质量的信心。

测试方法与技术

  • 机器测试

    在设定的测试数据上执行被测程序的过程。又称动态测试。

  • 人工测试

    采用人工方法进行,目的在于检查程序的静态结构,找出编译不能发现的错误。

人工测试分类

  • 代码审查
    以小组会的形式,发现程序在结构、功能、编码风格等方面存在的问题。可查出30%~70%的错误
  • 走查
    以小组会的形式进行,把测试数据“输入”到被测程序,并在纸上跟踪监视程序的执行情况,让人代替机器沿着程序的逻辑走一遍。
  • 桌前检查
    设计模块时,程序员自己检查。

机器测试分类

  • 黑盒测试

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

  • 白盒测试

白盒测试是对软件的过程性细节做细致的检查。
这一方法是把测试对象看做一个打开的盒子或透明的盒子,它允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。
通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。
因此,白盒测试又称为结构测试或逻辑驱动测试。

白盒测试的测试用例设计

逻辑覆盖

逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例

的技术,它属于白盒测试。

由于覆盖测试的目标不同,逻辑覆盖又可分为:

  • 语句覆盖
  • 判定覆盖
  • 判定—条件覆盖
  • 条件组合覆盖
  • 路径覆盖

语句覆盖

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

判定覆盖

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

条件覆盖

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

每个条件真假走一次

判定-条件覆盖

所谓判定-条件覆盖就是设计足够的测试用例,使得判断中
每个条件的所有可能取值至少执行一次,同时每个判断本身
的所有可能判断结果至少执行一次。

条件组合覆盖

条件组合覆盖就是设计足够的测试用例,运行被测程序,使得每个判断的所有可能的条件取值组合至少执行一次。

路径测试

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

基本路径覆盖

基本路径测试是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。

黑盒测试的测试用例设计

等价类划分

  • 等价类划分是一种典型的黑盒测试方法,也是一种非常实用的重要测试方法,它是用来解决如何选择适当的子集,使其尽可能多地发现错误。
  • 使用这一方法设计测试用例要经历划分等价类(列出等价类表)和选取测试用例两步。
划分等价类

所谓等价类是指某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的,并合理地假定:测试某等价类的代表值等价于对这一类其他值的测试。

等价类的划分

  1. 有效等价类

    有效等价类:是指对于程序的规格说明来说,是合理的、有意义的输入数据构成的集合。利用它,可以检验程序是否实现了规格说明预先规定的功能和性能。

  2. 无效等价类

    是指对于程序的规格说明来说,是不合理的、无意义的输入数据构成的集合。程序员主要利用这一类测试用例检查程序中功能和性能的实现是否有不符合规格说明要求的地方。

​ 在设计测试用例时,要同时考虑有效等价类和无效等价类的设计。

确定测试用例

在确定了等价类之后,建立等价类表,列出所有划分出的等价类,如下:

image-20240102162856504

再从划分出的等价类中按以下原则选择测试用例。
(1)为每一个等价类规定一个唯一的编号。
(2)设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止。
(3)设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止。

边界值分析

  • 边界值分析也是一种黑盒测试方法,是对等价类划分方法的补充。人们从长期的测试工作经验中得知,大量的错误是发生在输入或输出范围的边界上,而不是在输入范围的内部。
  • 这里所说的边界是指,相当于输入等价类和输出等价类而言,稍高于其边界值及稍低于其边界值的一些特定情况。

软件测试策略

通常软件测试过程按4个步骤进行,即单元测试组装测试(集成测试)确认测试系统测试。如下图所示。

image-20240102161943964

单元测试

单元测试(unit testing)又称模块测试,是针对软件设计的最小单位—程序模块,进行正确性检验的测试工作。其目的在于发现各模块内部可能存在的各种差错。单元测试需要从程序的内部结构出发设计测试用例。多个模块可以平行地独立进行单元测试。

单元测试内容

单元测试主要采用白盒测试方法设计测试用例,辅之以黑盒测试的测试用例,使之对任何合理的输入和不合理的输入,都能鉴别和响应。在单元测试中进行的测试工作如下图所示,需要在5个方面对被测模块进行检查。

image-20240102164134720
  1. 模块接口测试
  2. 局部数据结构测试
  3. 路径测试
  4. 错误处理测试
  5. 边界测试
单元测试步骤
  1. 驱动模块
  2. 桩模块
image-20240102185005911

组装测试

组装测试(integrated testing)也叫做集成测试或联合测试。通常,在单元测试的基础上,需要将所有模块按照设计要求组装成为系统,把模块组装为系统的方式有两种:一次性组装方式(big bang)和增值式组装方式。

确认测试

确认测试(validation testing)又称有效性测试。它的任务是验证软件的有效性,即验证软件的功能和性能及其他特性是否与用户的要求一致。在确认测试阶段需要做的工作如下图所示。

image-20240102185138824
  1. 进行有效性测试(黑盒测试)

  2. 软件配置复查

  3. α测试和β测试

    α测试是由一个用户在开发环境下进行的测试,也可以是公司内部的用户在模拟实际操作环境下进行的测试。软件在一个自然设置状态下使用,开发者坐在用户旁边,随时记下错误情况和使用中的问题。 α测试的目的是评价软件产品的FLURPS(即功能、局域化、可使用性、可靠性、性能和支持),尤其注重产品的界面和特色。

    β测试是由软件的多个用户在一个或多个用户的实际使用环境下进行的测试。这些用户是与公司签定了支持产品预发行合同的外部客户。与α测试不同的是,开发者通常不在测试现场,由用户记下遇到的所有问题。开发者在综合用户的报告之后进行修改,最后将软件产品交付给全体用户使用。β测试主要衡量产品的FLURPS,着重于产品的支持性,包括文档、客户培训和支持产品生产能力。只有当α测试达到一定的可靠程度时,才能开始β测试。

  4. 验收测试

  5. 确认结果测试

系统测试

系统测试(system testing)是将通过确认测试的软件,作为整个计算机系统的一个元素,与计算机硬件、外设、某些支持软件、数据、人员等其他系统元素结合在一起,在实际运行(使用)环境下,对计算机系统进行一系列的组装测试和确认测试。

系统测试的目的在于通过与系统的需求定义作比较,发现软件与系统定义不符合或与之矛盾的地方。系统测试的测试用例应根据系统的需求分析说明书设计,并在实际使用环境下运行。

测试的类型

(1)功能测试(function testing):功能测试是在规定的一段时间内运行软件系统的所有功能,以验证这个软件系统有无严重错误。

(2)回归测试(regression testing):这种测试用于验证对软件修改后有没有引出新的错误,或者说,验证修改后的软件是否仍然满足系统的需求规格说明。

(3)可靠性测试(reliability testing):如果系统需求说明书中有对可靠性的要求,则需进行可靠性测试。通常使用平均失效间隔时间(MTBF)与因故障而停机的时间(MTTR)来度量系统的可靠性。

(4)强度测试(stress testing):也称压力测试,是要检查在系统运行环境恶劣的情况下,系统可以运行到何种程度的测试。因此,进行强度测试,需要提供非正常数量、频率或总量资源来运行系统。实际上,这是对软件的“超负荷”环境或临界环境的运行检验。

(5)性能测试(performance testing):是要检查系统是否满足在需求说明书中规定的性能。特别是对于实时系统或嵌入式系统,软件只满足要求的功能而达不到要求的性能是不可接受的,所以还需要进行性能测试。

(6)恢复测试(recovery testing):恢复测试是要证实在克服硬件故障(包括掉电、硬件或网络出错等)后,系统能否正常地继续进行工作,并不对系统造成任何损害。

(7)启动/停止测试(startup/shutdown testing):这类测试的目的是验证在机器启动及关机阶段,软件系统正确处理的能力。包括反复启动软件系统(例如,操作系统自举、网络的启动、应用程序的调用等),以及在尽可能多的情况下关机。

(8)配置测试(configuration testing):这类测试是要检查计算机系统内各个设备或各种资源之间的相互连接和功能分配中的错误。配置测试主要包括以下3种。

① 配置命令测试:验证全部配置命令的可操作性(有效

性);特别对最大配置和最小配置要进行测试。软件配置

和硬件配置都要测试。

② 循环配置测试:证明对每个设备物理与逻辑的、逻辑

与功能的每次循环置换配置都能正常工作。

③ 修复测试:检查每种配置状态及哪个设备是坏的,并

用自动的或手工的方式进行配置状态间的转换。

(9)安全性测试(security testing):检验在系统中已经存在的系统安全性和保密性措施是否发挥作用,有无漏洞。为此要了解破坏安全性的方法和工具,并设计一些模拟测试用例对系统进行测试,力图破坏系统的保护机构以进入系统。

(10)可使用性测试(usability testing):可使用性测试主要从使用的合理性、方便性等角度对软件系统进行检查,以发现人为因素或使用上的问题。

(11)可支持性测试(supportability testing):验证系统的支持策略对于公司与用户方面是否切实可行。它所采用的方法是试运行支持过程(如对有错部分打补丁的过程,热线界面等),对其结果进行质量分析,评审诊断工具、维护过程、内部维护文档;衡量修复一个明显错误所需的平均最少时间。还有一种常用的方法是,在发行前把产品交给用户,向用户提供支持服务的计划,从用户处得到对支持服务的反馈。

(12)安装测试(installation testing):安装测试的目的不是查找软件错误,而是查找安装错误。在安装软件系统时,会有多种选择。要分配和装入文件与程序库,布置适用的硬件配置,进行程序的连接。而安装测试是要查找出在这些安装过程中出现的错误。

(13)互连测试(interoperability testing):验证两个或多个不同的系统之间的互连性。这类测试对支持标准规格说明,或承诺支持与其他系统互连的软件系统有效。

(14)兼容性测试(compatibility testing):验证软件产品在不同版本之间的兼容性。有两类基本的兼容性测试:向下兼容和交错兼容。向下兼容测试是测试软件新版本,保留它早期版本的功能的情况;交错兼容测试是要验证共同存在的两个相关但不同的产品之间的兼容性。

(15)容量测试(volume testing):容量测试是要检验系统的能力最高能达到什么程度。

(16)文档测试(documentation testing):检查用户文档(如用户手册)的清晰性和精确性。用户文档中所使用的例子必须在测试中一一试过,确保叙述正确无误。

软件维护

软件维护的概念

软件维护是指在软件运行/维护阶段对软件产品所进行的修改就是所谓的维护。

根据维护工作的性质,软件维护的活动可以分为以下4种类型。

  • 改正性维护
  • 适应性维护
  • 完善性维护
  • 预防性维护
image-20240103235351538

改正性维护

改正性维护(corrective maintenance)为了识别和纠正软件错误、改正软件性能上的缺陷、排除实施中的误使用,应进行的诊断和改正错误的过程。例如,改正性维护可以是改正原来程序中开关使用的错误;解决开发时未能测试各种可能情况带来的问题等。

适应性维护

随着信息技术的飞速发展,软件运行的外部环境(新的硬、软件配置)或数据环境(数据库、数据格式、数据输入/输出方式、数据存储介质)可能发生变化,为了使软件适应这种变化,而修改软件的过程叫做适应性维护(adaptive maintenance)。例如,需要对已运行的软件进行改造,以适应网络环境或已升级改版的操作系统要求。

完善性维护

为了满足新的功能与性能要求,需要修改或再开发软件,以扩充软件功能、增强软件性能、改进加工效率、提高软件的可维护性。这种情况下进行的维护活动叫做完善性维护(perfective maintenance)。

预防性维护

预防性维护(preventive maintenance)是指把今天的方法学用于昨天的系统以满足明天的需要。也就是说,采用先进的软件工程方法对需要维护的软件或软件中的某一部分(重新)进行设计、编码和测试。

重构

重构就是在不改变代码外在行为的前提下,修改代码来改进程序的内部结构,提高程序的可理解性和可维护性等,进而帮助尽早的发现缺陷,提高编程速度。