Contents

软件工程期末复习

Contents

软工期末复习

[TOC]

第 1 章 软件工程学概述

开发人员对软件的认识存在偏差,传统制造业等其他工程学的思想应用在软件开发

利用管理学的指导思想来指导软件开发,设计,系统与用户交互,软件测试,运维

软件定义

=软件是包括程序、数据及其相关文档组成的完整集合.=

软件的特点

  • 抽象特征
  • 无明显制造特征
  • 无备件特征
  • 手工制作特征
  • 成本昂贵

软件的分类

按软件功能分类

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

按照规模划分…

软件危机

开发与需求不匹配,研制周期长,正确性难以保证等,这些问题堆积起来成为了软件危机.

解决的不是技术上的问题,是管理上的问题

主要表现

  • 用户需求不明确(甲方)、变更过多
  • 软件成本日益增长
  • 开发进度难以控制
  • 软件质量差
  • 软件维护困难

产生原因

  • 软件开发无计划性
  • 软件需求不充分
  • 软件开发过程无规范
  • 软件产品无评测手段

解决途径

  • 应该加强软件开发过程的管理
  • 推广使用开发软件的成功技术和方法
  • 开发过程中使用好的工具

软件开发阶段

  • 程序设计阶段
  • 程序系统阶段
  • 软件工程阶段

软件工程要素

三要素:方法、工具、过程

软件工程目标

在给定成本、进度的前提下(开发人员等的工资),开发具有可修改性、有效性、可靠性、可理解性、可维护性、可重用性、可适应性、可移植性、可追踪性、可交互性并满足用户要求的软件产品.

软件开发技术包含:

  • 软件开发方法学
  • 软件工具
  • 软件工程环境
  • 软件工程管理

软件生存周期

孕育、诞生、成长、成熟、衰亡的过程

  • 计划
    • 问题定义
    • 可行性研究
  • 开发
    • 设计
      • 需求分析(结果:需求规格说明书)
      • 软件设计
        • 总体设计
        • 详细设计
    • 实现
      • 编码
      • 测试
  • 运行
  • 维护

软件生存周期模型

从需求定义到使用废弃,全部过程、活动和任务的框架

定义活动:做什么

开发活动:怎么做

维护活动:修改

瀑布模型
  • 顺序展开
截屏2025-03-08 17.11.35

每个阶段完成不会反工

过早考虑程序实现

必须每一阶段完成文档

要求:需求稳定(不适应需求变化)

螺旋模型

制作原型

截屏2025-03-08 17.14.13

每旋转一圈开发一个版本

有风险分析

适合风险大、不一定能一次到位的软件

第 2 章 可行性研究

问题定义

是软件工程第一个阶段,“需要解决什么问题

  • 总体目标
  • 功能和性能
  • 可靠性和质量
  • 是否具备可行的技术
  • 当前市场和竞争对手
  • 是否有成本和进度约束
  • 将来可能进行哪些扩充

可行性研究的主要目的是用极少的代价最短的时间内决定被开发的软件是否能开发成功

  • 经济可行性
  • 技术可行性
  • 法律可行性
  • 运行可行性

主要工具

==系统流程图==:用黑盒方式描述系统各部件的流动情况,不对信息在系统中加工细节描述,所以不同于程序流程图.

第 3 章 需求分析

需求分析主要目的是深入描述软件的功能和性能,确定软件设计的约束和软件同其他系统元素的**接口细节**,定义软件的其他有效需求(完全弄懂用户的所有需求)

“系统做什么”的问题,不包括“怎么做”

  • 确定目标系统的具体要求
    • 运行环境要求
    • 性能要求
    • 系统功能
  • 分析系统的数据要求
  • 建立目标系统的逻辑模型(理论上怎么实现,不考虑物理)
  • 修正系统开发计划
  • 建立原型系统
  • 编写原型系统
  • 编写软件需求规格说明书及评审

需求的获取

  • 访谈和会议
  • 市场调查
  • 访问用户和用户领域的专家
  • 考察现场,跟踪现场的业务流程
  • 开发人员和用户共同组成联合小组

需求分析的过程

  1. 问题识别(系统分析员:程序员和用户的中间人)

系统分析员要研究可行性分析报告和软件项目实施计划(上一阶段),主要从系统的角度来理解软件,评审是否恰当.确定对目标系统的综合要求(=软件的需求),并提出这些需求实现条件,以及需求应达到的标准.也就是解决要求被开发的软件用来做什么,做到什么程度,

持续到分析人员与用户双方都感到有把握正确的制定软件的需求规格说明为止

防止堆栈效应:越早潜入的错误越晚被发现

需求包含的内容

  • 功能需求
  • 性能需求
  • 环境需求
  • 可靠性需求
  • 安全保密要求
  • 用户界面要求
  • 资源使用需求
  • 软件成本消耗与开发进度需求
  • 预期系统可达到的目标

快速原型方法

原型:软件早期的一个版本,能够反映最终系统的一部分特性

快速分析构造出一个小型的软件系统,满足用户的基本要求;

用户在试用原型系统过程中得到亲身感受和受到启发,做出反应和评价

开发者根据用户的意见对原型加以改进,随着不断试验、纠错、使用、评价和修改,获得新的原型版本,如此周而复始,提高最终产品的质量.

原型的分类

  1. 废弃型

系统构造好后原型系统被废弃

  1. 追加型或演化型

先构想一个功能简单且质量要求不高的模型系统,最为最终系统的核心,然后通过不断的扩充修改发展为最终系统

结构化分析方法

截屏2025-03-08 20.41.28

核心:数据字典

  • 数据建模

用数据描述现实世界的信息,ER 图

  • 功能建模和数据流

用抽象模型概念,按照软件内部数据传递、变化的关系,自顶向下逐层分解,直到找到满足功能要求的所有可实现软件 数据流图

  • 行为建模

给出需求分析方法的所有操作原则 状态-迁移图

数据流图

Data Flow Diagram,DFD,是用来描述软件系统逻辑模型的图形工具,用于描述信息在系统中流动和处理的情况.设计 DFD 只需考虑软件系统必须完成的逻辑功能“做什么”

四种符号:

截屏2025-03-08 20.58.29

数据流:数据流动的方向

分层的时候:顶层图、一层图、二层图…

父图和子图输入输出应该相等

数据字典

数据字典(Data Dictionary,DD)是结构化分析方法的另一种有力工具,在数据字典中建立的一组严密一致的定义有助于消除分析员和用户之间的沟通障碍,因此将消除许多可能的误解.对数据的这一系列严密一致的定义也 有助于改进在不同的开发人员或不同的开发小组之间的通 信.同时,数据字典也是软件维护时使用的一种重要资料.如果要求所有开发人员都根据公共的数据字典描述数据和设计模块,则能避免许多麻烦的接口问题,提高开发的效率和质量.

是根据数据流的

内容:

  • 数据流词条描述
  • 数据项词条描述
  • 数据文件词条描述
  • 加工逻辑词条描述
  • 源点及汇点词条描述

数据流+数据存储+数据项(不可分解)

= 定义

+号 与…组成

[] | 组成

{} 重复 由 0 个或多个

() 可选 可以出现或不出现

m{}n 可出现 m-n 次

“…” 表示取…值的数据元素

.. 连接符 x=1..9 中任意一个

需求分析评审

确定需求规格说明书,是双方达成的协议书

需求分析实例

数据流图:

截屏2025-03-08 21.17.58 截屏2025-03-08 21.19.17

顶层图、一层图、二层图(自顶向下分解)

数据来源:外部实体

第 4 章 形式化说明技术

不考,无资料

第 5 章 总体设计

现在是到了软件设计阶段,上一阶段得到的结果是需求规格说明书,明确的描述了用户对系统的需求,现在要解决“怎么做”的问题

将软件需求转换为软件的表示过程

  1. 概要设计(总体):将软件需求转换为软件结构和数据结构,并编写概要设计说明书

  2. 详细设计:通过对软件结构的细化,得到软件的详细算法和数据结构,产生描述软件的详细设计文档

软件设计的基本概念

  • 逐步求精 先定义边界,再将功能拆解为若干个组合模块,越往下越细化,抽象性,每一个阶段都是对上一个阶段的求精.(可行性阶段,需求分析阶段,设计阶段,编码阶段)
  • 程序结构 划分模块,模块和模块之间的关系
  • 数据结构 是构成复杂结构的基本块
  • 局部化 将关系密切的元素靠近一些,有利于实现信息隐蔽,方便用户调用

模块化

模块是数据说明、语句等程序对象的集合,单独命名而且可以通过名字来访问,如**过程、函数、子程序、宏**

模块 3 个基本属性
  1. 功能:模块实现的功能(含子模块)
  2. 逻辑:模块内部怎么做
  3. 状态:模块使用时的环境和条件

模块具有内部和外部两个特性:

  1. 外部特性:模块的名字、参数等
  2. 内部特性:完成模块功能的程序代码和模块内部数据
模块的独立性

软件系统中每个模块只涉及软件要求的具体子功能,而和软件系统中其他的模块**接口是简单的**

  • 模块独立性高的软件容易开发,便于多人合作
  • 独立模块容易测试维护
  • 一般采用两个准则度量模块独立性,即==模块与模块之间的耦合度==和==模块内部的内聚性==
耦合性

耦合是程序结构内不同模块之间相互关联的度量.它是由模块间接口的复杂程度、调用模块的方式及通过接口传递的信息类型决定的.

模块之间的连接越紧密,联系越多,耦合性越高,而其模块独立性越弱

  1. 非直接耦合

如果两个模块之间没有直接关系,联系通过主模块的控制和调用实现的,这就是非直接耦合,模块独立性最强.

  1. 数据耦合

模块访问另一个时,彼此之间通过**数据参数(**不是控制参数、公共数据结构或外部变量)来交换输入、输出信息,为数据耦合.

限制了只通过参数表传送数据,所以按数据耦合开发程序接口简单,安全可靠.

数据耦合是松散的耦合,模块之间的独立性比较强.在软件设计中多用这种耦合.

  1. 特征耦合

如果一组模块通过参数表传递记录信息,就是特征耦合.

事实上,这组模块共享了某一数据结构的子结构,而不是简单变量.这就要求这些模块都必须清楚该记录的结构.

  1. 控制耦合

如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择被调用模块的功能,则称这种耦合为控制耦合.

实质是在单一接口上选择多功能模块中的某项功能.因此,对被控模块的任何修改,都会影响控制模块.另外,控制耦合也意味着控制模块必须知道被控模块的内部逻辑,这些会降低模块的独立性.

  1. 外部耦合

一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量,则称为外部耦合.外部耦合引起的问题类似于公共耦合,区别在于外部耦合不依赖于一个数据结构内部各项的程序逻辑.

  1. 公共耦合

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

  1. 内容耦合

如果一个模块直接访问另一个模块的内部数据;或者一个模块不通过正常入口转到另一模块内部;或者两个模块有一部分程序代码重叠;或者一个模块有多个入口,则两个模块之间就发生了内容耦合.

在内容耦合的情况下,被访问模块的任何变更,或者用不同的编译器对它再编译.都会造成程序出错.这种耦合是模块独立性最弱的耦合.

内聚性

标志一个模块内部各元素彼此结合的紧密程度

  1. 偶然内聚

程序内几个模块内凑巧有一些程序段代码相同,又没有明确表现出独立的功能,这些代码独立出来建立的模块称为偶然内聚

  1. 逻辑内聚

一个模块几种相关的功能组合在一起,每次被调用时,由传送给模块的控制参数来确定模块应该执行哪种功能.逻辑内聚导致模块间的控制耦合

  1. 时间内聚

时间内聚大多为多功能模块,要求模块的各个功能必须在同一时间段内进行,如初始化模块或结束模块.在一般情形下,各部分可按任意的顺序执行,所以它的内部逻辑更简单.

  1. 过程内聚

如果模块内的处理是相关的,并且必须以特定顺序执行.

使用流程图作为工具设计工具时,常常通过流程图去确定模块划分.把流程图某一部分划出独立模块,就得到过程内聚模块.

  1. 通信内聚

一个模块内各部分功能都使用了相同的输入数据,或者产生了相同的输出数据,则称之为通信内聚模块,通常通信内聚模块是通过==数据流图==来定义的.

  1. 信息内聚

模块完成多个功能,各个功能都在同一数据结构上操作,每一项功能都有一个唯一的入口点,信息内聚模块可以看成是多个功能内聚模块的组合,并且实现信息上的隐蔽.

即把某个数据结构、资源或设备隐蔽在一个模块内,不为别的模块所知晓.这种封装增加了模块的独立性

  1. 功能内聚

一个模块的各个功能都是完成某个具体任务必不可少的,这些成分协同工作,紧密联系,不可分割.

功能内聚的内聚度最高,满足功能内聚的模块执行一个功能,这是判断模块是否是功能内聚的一个方法.

抽象

抽象(Abstration)就是提取出事物的本质特征而暂时不考虑它们的细节.

在软件设计中,涉及到众多的物理元素,如果一开始就考虑细节问题,不可能做到精确思维.抽象化对于软件设计十分重要.

软件设计中可以有不同的==抽象层次==,最高层次抽象上,用问题所处环境的语言,概括描述问题的解答.在最低层次,用直接实现的方式来描述问题的解答.

抽象三个层次
  1. 过程抽象

从问题定义到程序的实现(代码),每个步骤逐步细化;抽象层次逐渐降低

  1. 数据抽象

在不同抽象层次上描述数据对象的细节,数据抽象把一个数据对象的定义抽象为一个数据类型名.(比如定义一个人的时候 Person 为相同性质一堆人的抽象)确定实体和对应的操作

  1. 控制抽象

可以包含一个程序控制机制而无需规定其内部细节.(操作系统中协调活动的同步信号)

信息隐蔽:目的是提高模块的独立性,(信息内聚),不要把 A 模块的错误扩散到其他 B 模块.

软件设计的基本原则

  1. 功能分解
  2. 设计对分析模型是可跟踪的
  3. 设计结构应尽可能模拟实际问题
  4. 设计应该表现出一致性
  5. 不要把设计当成编写代码
  6. 创建设计时就应该能够评估质量
  7. 设计阶段注重软件的重用
  8. 评审设计以减少语义性的错误

结构化设计方法 SD

面向数据流的设计方法,基于模块化,自顶向下逐层细化

基于数据流图审查和分析,改进细致处理,生成对应数据字典

系统结构图 SC

Structed Chart 是 SD 方法使用的主要描述工具,描述**软件的组成模块和调用关系**

由四个模块组成:传入模块,传出模块,变换模块,协调模块

  • 简单调用
  • 选择调用
  • 循环调用

所有 DFD 结构可以分为:变换型,事务型

  • 变换型结构==输入数据、变换数据、输出数据==
  • 事务型结构 ==有明显事务中心==
变换分析

将变换型数据流图映射为软件结构图一系列步骤总称

截屏2025-03-09 14.33.16

==重新画数据流图==,不要出现控制逻辑,箭头表示数据流向

截屏2025-03-09 14.34.15

这个图有中心变换部分,所以是变换型的

截屏2025-03-09 14.35.48

将数据流图转换为软件结构图,建立总控模块

第 6 章 详细设计

上面的软件结构还不够实现开发,需要进行详细设计,例如程序流程图

截屏2025-03-09 14.37.31

箭头流向表示程序执行顺序,菱形表示判断和选择

盒图(程序设计)(Box-Diagram)(N-S 图)

N-S 图也称盒图,是一种符合结构化程序设计原则的图形描述工具.

结构化程序设计要求只使用 3 种基本控制结构,即顺序结构、分支结构(简单选择型和多分支选择型)和循环结构(包括先判定型和后判定型)

截屏2025-03-09 14.41.15
  • 每个矩形框都是明确定义的功能域
  • 控制转移不能任意规定,必须遵循结构化程序要求
  • 很容易确定局部数据和全局数据的作用域
  • 很容易表现嵌套关系和模块的层次结构

PAD(Problem Analysis Diagram)问题分析图

日本公司提出的结构化程序设计思想表现程序逻辑结构的图形工具

也设计了 5 种基本控制结构的图式,并允许递归使用

截屏2025-03-09 14.45.57

判定树&判定表

当算法中包含**===多重嵌套的条件选择==时,用程序流程图、 N-S 图或 PAD 都不易清楚地描述.这时可以用 或判定树来描述这些复杂的条件.判定表与判定树除了在详细设计阶段使用外,在需求分析阶段也经常使用.判定表一般由4 部分组成**:左上半部分列出所有条件、 左下半部分列出所有动作、右上半部分列出各种条件组合,右下半部分列出和每组条件取值组合对应的动作.

截屏2025-03-09 14.49.16

判定表的优点是能够简洁,无二义性的描述所有的处理规则。缺点是它所表示的是静态逻辑,是在某种条件组合情况下可能的结果,它不能表达加工的顺序,也不能表达循环结构.因此,判定表不能成为一种通用的设计工具,一般作为辅助工具配合其他工具一起使用。

截屏2025-03-09 14.50.17

判定树

判定树是判定表的变形,本质一样.

优点:形式简单、比较直观、易于掌握和使用,缺点是不如判定表简洁

截屏2025-03-09 14.55.01

第 7 章 实现

编码风格

  • 编码风格的作用就是使==代码容易读==;
  • 风格良好的代码更容易阅读和理解,错误更少;
  1. 使用一致和有意义的标识符名
  2. 缩进显示程序结构
  3. 加括号的方式排除二义性
  4. 避免大量使用循环嵌套和条件嵌套
  5. 当心运算符的副作用
  6. 把数定义成常量
  7. 利用 sizeof()计算对象的大小
  8. 清晰的代码,而非最巧妙的代码
  9. 程序的注释
    1. 序言性注释和功能性注释
    2. 对一段程序注释,而不是每一个语句
  10. 使用数据结束标记(EOF、BOF),不要指定数据的数目来判断文件的结束。

测试

  • 测试的==目的==就是在软件投入==生产性运行==之前,尽可能多地==发现软件中的错误==。

  • 调试的==目的==是**==诊断并改正==错误,由程序员完成。**

  • 对软件规格说明、设计和编码的最后复审。

  • 开发总工作量的 40%以上,极端情况下,其他开发步骤总成本的3 倍到 5 倍

  • 测试是为了发现程序中的错误而执行程序的过程。

  • 好的测试方案是极可能发现迄今为止尚未发现的错误的测试方案

  • 成功的测试是发现了至今为止尚未发现的错误的测试。

  • 测试只能查找出程序中的错误,不能证明程序中没有错误

  • Pareto 原理:80%的错误很可能是 20%的模块造成的。从“小规模”测试逐步到“大规模”测试。

  • 穷举测试是不可能的。

  • 为了达到最佳的测试效果,应该由独立的第三方从事测试工作。

测试方法

  • ==黑盒==测试:又称功能测试数据驱动测试
  • ==白盒==测试:又称结构测试逻辑驱动测试
黑盒测试

功能测试或数据驱动测试(问诊)

  • 等价划分
    • 把输入域分为数据类,取每类的一个典型值进行测试
    • 新增测试用例尽可能多地覆盖尚未被覆盖的有效等价类
    • 新增测试用例覆盖一个尚未被覆盖的无效等价类
  • 边界值测试
    • 着重测试输入等价类和输出等价类的边界,选取的测试数据应该刚好等于、刚好小于和刚好大 于边界值
  • 用等价划分和边界值分析法设计测试用例
  1. 等价划分

    • 把程序的输入域划分成若干个==数据类==,每类中的一个典型值在测试中的作用与这一类中所有其他值的作用相同。据此导出测试用例。
    • 设计测试用例
      • (1) 设计一个新的测试方案以尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步骤直到所有有效等价类都被覆盖为止;
      • (2) 设计一个新的测试方案,使它覆盖一个而且只覆盖一个尚未被覆盖的无效等价类,重复这一步骤直到所有无效等价类都被覆盖为止。
  2. 边界值分析

    • 着重测试输入等价类和输出等价类的边界,选取的测试数据应该刚好等于、刚刚小于和刚刚大于边界值。

要求:会用==等价划分==和==边界值分析法==设计测试用例

白盒测试

结构测试或逻辑驱动测试(手术) 以程序内部逻辑结构为基础的设计测试用例的技术 语句覆盖:每个语句至少执行一次 判定覆盖(分支覆盖):每个判定的每个分支至少执行一次 条件覆盖:每个判定的每个条件都取到可能的值,每个判定的分支至少执行一次

  • 条件组合覆盖:每个判定中的各种条件组合都至少执行一次(对源程序语句检测详尽程度最高)

点覆盖、边覆盖、路径覆盖(顾名思义)

白盒测试技术:逻辑覆盖

定义:以==程序内部的逻辑结构为基础的设计测试用例==的技术

类型

  1. 语句覆盖:选择足够多的测试数据,使被测程序中每个语句至少执行一次。

  2. 判定覆盖:判定覆盖又叫分支覆盖,选择足够多的测试数据使每个判定的每个分支都至少执行一次

  3. 条件覆盖:选择足够多的测试数据使每个判定表达式中的每个条件都取到各种可能的结果

  4. 判定/条件覆盖:选取足够多的测试数据,使得判定表达式中的每个条件都取到各种可能的值,而且每个判定表达式也都取到各种可能的结果。

  5. 条件组合覆盖:选取足够多的测试数据,使得每个判定表达式中条件的各种可能组合都至少出现一次。(最好)

要求:设计测试用例(==会做==)

可以把「黑盒测试」和「白盒测试」想象成买东西时的两种“体验”: 1. 黑盒测试就好比你买了一个手机,只关注它能不能正常打电话、拍照、上网,不关心它内部的芯片、电路是怎么工作的。 • 测试时,你只需要根据需求或者说明书来试一下各种功能:比如能不能拨打电话,能不能拍照,能不能用微信等。 • 你并不用去了解它是如何编程实现的,也不用查看源代码,只要功能“用起来”符合要求就行。 2. 白盒测试则像你是个电子工程师或手机设计师,知道手机里每块芯片、每行电路的具体功能,你会检查它们是不是都正确地运转。 • 测试时,你需要查看手机内部的工作原理,比如 CPU 各个功能模块有没有正确执行,或者手机系统软件中每个函数、每条分支都有没有被测试到。 • 你不只是看“能不能打电话”,你还会看代码里“如果没插卡时,程序是不是应该给出提示?”、“所有条件分支是不是跑了一遍?”等等。

总结:黑盒测试只关心“外在表现”(功能是否正确),白盒测试则还要研究“内部结构”(代码或逻辑是否正确)。

测试步骤

  • 模块测试(单元测试)
    • 在这个测试步骤中所发现的往往是编码和详细设计的错误
  • 子系统测试
    • 模块放在一起形成一个子系统来测试
    • 着重测试模块的接口
  • 系统测试
    • 经过测试的子系统装配成一个完整的系统来测试
    • 发现的往往是软件设计中的错误,也可能发现需求说明中的错误
  • 验收测试(确认测试)
    • 它的目标是验证软件的有效性(如果软件的功能和性能如同用户所合理期待的那样,软件就是有效的)
    • 用户积极参与,可能主要使用实际数据进行测试
    • 发现的往往是系统需求说明书中的错误
  • 平行运行

回归测试

回归测试是指重新执行已经做过的测试的某个子集以保证变化(程序改错、新模块加入等)没有带来非预期的副作用

  • Alpha 测试
    • 在开发者的“指导”下,由用户在开发场所进行。
  • Beta 测试
    • 多个用户在实际使用环境下进行测试。

集成测试方法

  • 非渐增式集成
    • 分别测试每个模块,再把所有模块按设计要求放在一起结合成所要的程序。
    • 先进行单元测试,再进行集成测试
  • 渐增式集成
    • 单元测试与集成测试结合在一起,把下一个要测试的模块同已经测试好的那些模块结合起来进行测试,测试完以后再把下一个应该测试的模块结合进来测试。
    • 自顶向下(Top-Down)集成
    • 自底往上(Bottom-Up)集成
    • 三明治式(Sandwich)集成
几种集成测试方法的优缺点
image-20250309165114278

第 8 章 维护

  • 所谓软件维护就是在软件已经交付使用之后,为了改正错误或满足新的需要而==修改软件==的过程。保证软件在一个相当长的时期能够==正常运行==。

  • 60%以上, 这个百分比还在持续上升。

维护类型

改正性维护

诊断和改正错误的过程。17%~ 21%

适应性维护

为了适应环境的变化进行的修改软件的活动。 18%~ 25%

完善性维护

增加新功能或修改已有功能。 50%~ 66%

预防性维护

为了改进未来的可维护性或可靠性,或为了给未来的改进奠定更好的基础而修改软件。4%左右

软件的可维护性

  • 维护人员理解、改正、改动或改进这个软件的难易程度。

  • 提高可维护性是支配软件工程方法学所有步骤的关键目标。

决定软件可维护性的因素

  • 1)可理解性

  • 2)可测试性

  • 3)可修改性

  • 4)可移植性

  • 5)可重用性

第 9 章 面向对象方法学引论

基本概念 OOP 学过了,差不多都会

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

对象:为它本身的一组属性和它可执行的一组操作

:一组具有相同数据结构和相同操作的对象的集合

继承:从已存在的类为基础建立新类的技术

应用生存期

瀑布模型是生存期模型.

面向对象开发步骤:

  • 分析阶段
  • 高层设计
  • 类的开发
  • 实例的建立
  • 组装测试
  • 应用与维护
截屏2025-03-09 15.00.03

上一个阶段的成果作为下一阶段的基础

类生存期

在面向对象技术中,类是作为一个单元存在的。不断有新的类在系统开发的各个阶段被标识,但在各个阶段的类所起的作用不同的。类的开发有如下几个步骤:

  • 类的规格说明
  • 设计
  • 实现
  • 测试
  • 求精和维护
截屏2025-03-09 15.01.54

UML(Unified Method Language)统一建模语言

工具:建模面向对象技术的==标准==语言

UML 是一种可视化的、用于绘制==软件蓝图==的标准建模语言。可以用 UML 对软件系统的各种制品(包括程序、文档等)进行描述

UML 作为一种语言提供了用于交流的词汇表和使用这些词汇的规则,它由一些符号一套指示如何使用这些符号的规则构成,可以利用这些明确定义的符号和相应的规则,建立待开发系统的各种模型。

  • 利用面向对象技术为系统建模
  • 易于使用、表达性强,进行可视化建模
  • 与具体实现无关,适用于任何语言和平台
  • 具有较强的适用性和可扩展性

使用面向对象技术设计系统时,首先是描述需求。其次根据需求建立系统的静态模型,构造系统的结构。这两步所建立的模型都是静态的,属于==UML 中的静态建模机制==。 第三步是描述系统的行为。这一步骤中建立的模型或者可以执行,或者表示执行时的时序状态或交互关系,是标准建模语言 UML 的==动态建模机制==。 因此,标准建模语言 UML 的主要内容也可以归纳为静态建模机制和动态建模机制两大类。

UML 三个主要要素
  • UML 基本构造块
  • 控制构造块如何组合的规则
  • 作用域 UML 模型的通用机制

按照层次结构划分,UML 基本构造块包含:

  • 视图(View)
  • 图(Diagram)
  • 模型元素(Model Element)

视图

视图是用来显示系统的不同方面。视图并不是图形(Graph),而是由多个图(Diagram)构成的,是在某一个抽象层上对系统的一个抽象表示。

  • 用例视图
  • 逻辑视图
  • 并发视图
  • 组件视图
  • 部署视图

图用来描述一个特定视图的内容。 UML 中的图由各种图形构成,图形就是各种模型元素符号。UML 提供了静态图和动态图两大类共 9 种图,用来描述系统的所有视图。

  • 静态图

    • 包括==用例图==、==类图==、==对象图==、组件图和部署图
  • 动态图

    • 包括==状态图==、==时许图==、协作图和活动图

UML 模型元素&表示方法

在 UML 各种图中使用的概念统称为模型元素。模型元素主要是用标准的图形符号表示的,图形符号本身代表了 UML 的语法。由这些==图形符号==组成的各种模型,则给出 UML 的语义。

  • 第一类模型元素(图形)表示某个概念
    • 类、对象、组件、状态、用例(用户(或其他系统)与目标系统之间的一种交互场景)、结点、接口、包、注释等
  • 第二类表示模型元素之间相互连接的关系(关系也是模型元素)
    • 关联、泛化、依赖、聚集
截屏2025-03-09 15.57.08

UML 元模型结构

UML 模型按照语义可定义为 4 个抽象层次。从低到高分别是元元模型元模型模型用户模型。下一层是上一层的基础,上一层是下一层的实例

截屏2025-03-09 15.58.27

示例

截屏2025-03-09 15.59.14 截屏2025-03-09 16.00.48

可将==许多类==集合成一个更高层次的单位, 形成一个高内聚、低耦合的类的集合。UML 把这种将一些模型元素组织成语义上相关的组的分组机制叫包 (Package)。 包中的所有模型元素叫作包的内容。包有时也称子系 统,常用于对模型的组织管理。包的实例没有任何语义,仅在模型执行期间,包才有意义。 包与包之间可以有关系,允许的关系有:依赖、细化和 泛化

UML 扩展机制

  • 构造型
  • 标记值
  • 约束

UML 的规则

UML 就是一种由符号和一套指示如何使用这些符号的 规则组成的建模语言。其中,符号就是在模型中使用的符号,规则包含语法规则语义规则实用规则

  • 命令:为模型起一个名字
  • 范围:给模型元素上下文
  • 可见性:让其他元素看见此元素
  • 完整性:各模型如何正确一致联系
  • 执行:运行或模拟动态模型的含义是什么

静态建模

静态模型-==用例模型==

一组用例图组成,其基本组成部件是==用例、角色和系统==。用例是系统中的一个功能单元,是对系统的一个 用法的通用描述。用例描述的是系统的总体功能。用例之间的关系主要有 3 种:泛化关系、扩展关系和包含关系

截屏2025-03-09 16.06.39

人:具体角色/系统,是==执行用例的主体==(参与者)

圆圈:具体的==用例==表示系统的==功能单元==

圆圈之间:==泛化(Generalization)==关系、==扩展(extends)==关系、==包含(includes)==关系

在软件工程和 UML(统一建模语言)中,用例之间常见的三种关系是:

  1. Include(包含)

• 用例 A 在执行过程中“包含”了用例 B,意味着 A 的部分流程需要调用(或复用)B 的功能。

使用场景:当多个用例都会用到同一段通用逻辑时,可以把这段逻辑抽取成一个独立的用例 B,再由其他用例通过 include 的方式来调用它。

特点:被包含的用例是必要的,不执行 B 用例便无法完成 A 的完整流程。

  1. Extend(扩展)

• 用例 A 在某个条件下被用例 B “扩展”,即在 A 的基础流程里,若满足某些条件,会触发 B 的额外步骤或不同分支。

使用场景:当你想在 A 用例的基础流程上,针对特定的情况或条件,增加额外处理或改变流程,而这部分逻辑并非所有情况下都执行。

特点:被扩展的用例是可选的,仅在满足扩展条件时才会发生。

  1. Generalization(泛化/继承)

• 用例 A 是用例 B 的“泛化”或“子用例”,表示 A 继承了 B 的主要流程,并可在其中增补或修改特定步骤。

使用场景:当多个用例有相同的大部分流程,但在细节或约束上略有不同时,可以让子用例继承父用例的大部分描述,并在子用例中做针对性扩展或重写。

特点:父用例抽象了共同行为,子用例可覆盖或补充父用例的部分流程。


总结

Include 侧重于将公共或必需的功能拆分,减少重复。

Extend 适用于条件下的可选或额外流程。

Generalization 适用于同一功能族中不同用例间的继承与差异化。

这三种关系能帮助我们在用例图中更好地表达各用例间的复用、扩展以及层次结构,从而让需求和设计更加清晰。

用例模型在需求分析阶段进行

静态模型-==类和对象模型==

在 UML 中,类和对象模型分别由类图和对象图表示。类是用一个矩形表示的,并且该矩形由 3 部分组成:名称部分属性部分操作部分

截屏2025-03-09 16.16.32

对象与类具有相同的表示形式。对象图可以看作是类图的一个实例;对象之间的链是类之间相互关联的实例。对象与类的图形表示相似。

截屏2025-03-09 16.19.00
类之间的关系
  1. 关联关系
截屏2025-03-09 16.19.39

菱形放在包含(多)的一端

  1. 聚集关系
截屏2025-03-09 16.20.07
  1. 泛化关系
截屏2025-03-09 16.21.33
  1. 依赖关系和细化关系
截屏2025-03-09 16.21.54

动态建模

消息

UML 的 4 个动态模型均采用消息这个概念。对象通过相互间的通信(消息传递)进行合作,并在其生命周期中根据通信的结果不断改变自身的状态

截屏2025-03-09 16.24.20
动态模型-==状态图==

用来描述一个特定对象的所有**可能状态及引起其状态转移**的事件。一个状态图包括一系列的状态以及状态之间的转移。

截屏2025-03-09 16.25.37
  • 状态
  • 状态转移
  • 事件(箭头)
  • 状态图之间发送消息
动态模型-时序图

用来描述对象之间动态的交互关系,着重体现对象间消息传递的时间顺序。 时序图存在两个轴:水平轴表示不同的对象,垂直轴 表示时间。时序图中的对象用一个带垂直虚线的矩形框表示,并标有对象名和类名。垂直虚线是对象的生命线, 用于表示在某段时间内对象是存在的。对象间的通信通过在对象的生命线间传递消息来表示。消息的箭头指明消息的类型

![截屏2025-03-09 16.28.24](/assets/截屏 2025-03-09 16.28.24.png)

协作图:相互协作对象交互关系和链接关系,着重体现交互对象静态链接关系

活动图:显示动作及其结果,通过对象图状态变化来获取动作和结果.

第 10 章 面向对象分析

面向对象分析(OOA,Object-Orientied Analysis):面向对象分析最后得到的是对==问题论域的清晰、精确的定义==。属于软件开发过程中的==问题定义阶段==,产生==描述系统功能==和==问题论域==的基本特征的综合文档

论域分析

Domin Analysis:在一个更广泛的领域考虑问题,把相关的概念都标识到,以便核心知识掌握得更好

  1. 语义数据模型(semantic data model) ==3 层模型==
  • 外部模型
  • 概念模型
  • 内部模型
  1. 在语义数据模型中的关系
  2. 标识对象和类
  3. 标识联系

应用分析

论域分析时建立起来的问题论域模型是应用分析的依据,要把它们用于当前正在建立的系统当中。在应用分析阶段产生影响的条件则伴随用某种基于计算机系统的程序设计语言来表示。重点考虑应用视图和类视图。必须详细描述对每个类的规格说明和操作,同时表示形成系统结构的类之间的相互作用

对象模型技术 OMT(Object Model Technology)

把分析时收集信息构造在 3 类:对象模型、动态模型、功能模型

截屏2025-03-09 15.10.24

这个模型化的过程是一个迭代的过程。每一次迭代都将对这 3 个模型做进一步的检验、细化和充实

对象模型

它的作用是描述系统的静态结构,包括构成系统的类和对象,它们的属性操作,以及它们之间的联系

截屏2025-03-09 15.11.45

对象图是类图的细化

“用例”所描述的功能 ≈ “对象模型中某些类所提供的服务”

属性:描述静态特征

方法/操作:描述动态特征

截屏2025-03-09 15.13.33

也可以使用==整体和实例进行组合/聚合技术==来描述面向对象分析

截屏2025-03-09 15.14.47

建立对象模型的步骤:

  • 确认对象和类
  • 建立数据字典
  • 加入对象间的关联
  • 确认对象属性
  • 使用继承加强类之间的联系
  • 确定存取数据的可能路径
  • 反复修正对象模型

动态模型

系统的涉及时序和改变的状况,可用动态模型来描述。 动态模型着重于系统的控制逻辑。它包括两个图:状态图事件追踪图

建立动态模型步骤:

  • 确认事件记录
  • 确认对象的事件
  • 准备每个程序事件追踪图
  • 确保对象间事件的一致性

功能模型

(e.g 系统流程图就是功能模型,可行性研究阶段)

功能模型着重于系统内部数据的传送和处理。功能模型由多个数据流图组成,它们指明从外部输入,通过操作和内部存储,直到外部输出的整个的数据流情况。

截屏2025-03-09 15.20.41

建立功能模型步骤:

  • 确定输入输出数据
  • 建立每个系统的功能
  • 确认对象间的限制
  • 详述最优系统分析准则

第 11 章 面向对象设计

高层设计

高层设计开发系统的结构,用来构造系统的总体模型,并把任务分配给系统的各个子系统。

  • 最小化构件间通信(高内聚,低耦合)
  • 隐藏复杂性
  • 逻辑功能分组
截屏2025-03-09 15.23.40

类的设计

核心原则:通过==复用==去设计类

选择、分解、配置、演变

应用系统的实现是在所有的类被实现之后完成的

软件复用

现有的软件成分构造的软件系统,包括两方面

  • 开发软件构件的技术
  • 使用软件构件的技术

e.g.活字印刷=>每一个文字都进行抽取,只需要后续进行排版、组装

软件复用的范围不仅涉及源程序代码,还包括==体系结构==、 ==需求模型==和==规格说明==、==各种设计==、==用户界面==、==数据==、==测试用例==、==用户文档==和==技术文档==,还有==项目计划==、==成本估计==等。将这些软件制品分为以下几类:

  1. 源代码复用
  2. 软件体系结构复用
  3. 应用程序生成器
  4. 特定论域的软件体系结构的复用
论域工程

通过领域分析找出最优复用,设计构造成可复用构件,建立大规模的软件构件仓库的过程

截屏2025-03-09 15.31.50
应用系统工程

通过复用构件系统开发某个特定应用系统的构件工程称为应用系统工程(ASE)