软件工程复习笔记
软件工程复习笔记
第1章 软件工程学概述
1.1 软件危机
1.1.1 软件危机的介绍
软件危机(软件萧条、软件困扰):指在计算机软件的开发和维护过程中所遇到的一系列严重问题。
软件危机的核心问题(两方面):
-
如何开发软件,满足对软件日益增长的需求;
-
如何维护数量不断膨胀的已有软件。
软件危机的典型表现(7点):
-
对软件开发成本和进度的估计常常很不准确;
-
用户对“已完成的”软件系统不满意的现象经常发生;
-
软件产品的质量往往靠不住;
-
软件常常是不可维护的;
-
软件通常没有适当的文档资料;
-
软件成本在计算机系统总成本中所占的比例逐年上升;
-
软件开发生产率提高的速度,远远跟不上计算机应用迅速普及深入的趋势。
1.1.2 产生软件危机的原因
-
与软件本身的特点有关;
-
与软件开发与维护的方法不正确有关。
1.1.3 消除软件危机的途径
-
对计算机软件有正确的认识;
-
认识到软件开发是一种组织良好、管理严密、各类人员协同配合、共同完成的工程项目;
-
推广使用在实践中总结出来的开发软件的成功技术和方法,并继续研究探索;
-
开发和使用更好的软件工具。
总结:解决软件危机,既要有技术措施(方法和工具),又要有必要的组织管理措施。
1.2 软件工程
1.2.1 软件工程的介绍(期中考重点)
软件工程:是指导计算机软件开发和维护的一门工程学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程。
软件工程的本质特性(7点):
-
软件工程关注于大型程序的构造;
-
软件工程的中心课题是控制复杂性;
-
软件经常变化;
-
开发软件的效率非常重要;
-
和谐地合作是开发软件的关键;
-
软件必须有效地支持它的用户;
-
在软件工程领域中是由具有一种文化背景的人替具有另一种文化背景的人创造产品。
1.2.2 软件工程的基本原理(7条)
-
用分阶段的生命周期计划严格管理;
-
坚持进行阶段评审;
-
实行严格的产品控制;
-
采用现代程序设计技术;
-
结果应能清楚地审查;
-
开发小组的人员应该少而精;
-
承认不断改进软件工程实践的必要性。
1.2.3 软件工程方法学
软件工程包括技术和管理两方面的内容。
软件工程方法学3要素:方法、工具、过程
两种主要方法学:
-
传统方法学(生命周期方法学或结构化范型)——强调自顶向下;
-
面向对象方法学——强调主动地多次反复迭代,其4个要点:对象、类、继承、消息。
1.3 软件生命周期(必考)
软件生命周期由软件定义、软件开发和运行维护(也称为软件维护)三个时期组成,每个时期又进一步划分成若干个阶段,共八个阶段。
| 三个时期 | 八个阶段 |
|---|---|
| 软件定义时期 | 问题定义、可行性研究、需求分析 |
| 软件开发时期 | 概要设计、详细设计、编码和单元测试、综合测试(系统设计、系统实现包含其中) |
| 运行维护时期 | 运行维护 |
1.4 软件过程
主要过程模型(5种):
-
1.4.1 瀑布模型;
-
1.4.2 快速原型模型;
-
1.4.3 增量模型;
-
1.4.4 螺旋模型;
-
1.4.5 喷泉模型。
第2章 可行性研究
2.1 可行性研究的任务
可行性研究的目的:不是解决问题,而是确定问题是否值得去解决。
可行性研究的实质:进行一次大大压缩简化了的系统分析和设计的过程,也就是在较高层次上以较抽象的方式进行的系统分析和设计的过程。
可行性研究的内容:
-
首先进一步分析和澄清问题定义,导出系统的逻辑模型;
-
然后从系统逻辑模型出发,探索若干种可供选择的主要解法(即系统实现方案);
-
对每种解法都研究它的可行性,至少从三方面研究。
可行性研究的主要方面:技术可行性、经济可行性、操作可行性;
其他方面:运行可行性、法律可行性。
2.2 可行性研究过程(8步)
-
复查系统规模和目标;
-
研究目前正在使用的系统;
-
导出新系统的高层逻辑模型;
-
进一步定义问题;
-
导出和评价供选择的解法;
-
推荐行动方针;
-
草拟开发计划;
-
书写文档提交审查。
2.3 系统流程图
系统流程图:是概括地描绘物理系统的传统工具。表达的是数据在系统各部件之间流动的情况,而不是对数据进行加工处理的控制过程。
2.4 数据流图
2.4.1 符号
基本符号:
-
数据存储:处于静止状态的数据;
-
数据流:处于运动中的数据。
附加符号:
-
星号(*):表示“与”关系;
-
加号(+):表示“或”关系;
-
异或(⊕):表示互斥关系。
2.5 数据字典
数据流图和数据字典共同构成系统的逻辑模型。
2.5.1 数据字典的内容
数据字典的组成:数据流、数据流分量(即数据元素)、数据存储、处理。
2.5.2 定义数据的方法
方法:对数据自顶向下分解。
数据组成方式(三种基本类型:顺序、选择、重复;附加类型:可选)
常用符号及含义:
-
=:等价于(或定义为);
-
+:和(即,连接两个分量);
-
[]:或(即,从方括弧内列出的若干个分量中选择一个,通常用“|”号隔开供选择的分量);
-
{ }:重复(即,重复花括弧内的分量;常常使用上限和下限进一步注释);
-
():可选(即,圆括弧里的分量可有可无)。
2.5.3 数据字典的实现
两种实现方式:计算机实现、人工实现。
2.6 成本/效益分析
2.6.1 成本估计(3种方法)
-
代码行技术;
-
任务分解技术;
-
自动估计成本技术。
2.6.2 成本/效益分析的方法
成本/效益分析涉及的4个概念:
-
货币的时间价值;
-
投资回收期;
-
纯收入;
-
投资回收率: P=F1/(1+j)+F2/(1+j)2+⋯+Fn/(1+j)nP = F_1/( 1 + j) + F_2/( 1 + j)^2 + \dots+ F_n/( 1 + j)^nP=F1/(1+j)+F2/(1+j)2+⋯+Fn/(1+j)n 。
第3章 需求分析
需求分析的核心任务:需求分析是软件定义时期的最后一个阶段,它的基本任务是准确地回答“系统必须做什么?”这个问题,确定系统必须完成哪些工作,也就是对目标系统提出完整、准确、清晰、具体的要求。系统分析员应该写出软件需求规格说明书,以书面形式准确地描述软件需求。
3.1 需求分析的任务(4点)
-
确定对系统的综合要求;
-
分析系统的数据要求;
-
导出系统的逻辑模型;
-
修正系统开发计划。
3.1.1 确定对系统的综合要求(8点)
-
功能需求;
-
性能需求;
-
可靠性和可用性需求;
-
出错处理需求;
-
接口需求;
-
约束;
-
逆向需求;
-
将来可能提出的要求。
3.1.2 分析系统的数据要求
-
建立数据模型——ER图;
-
描绘数据结构——层次方框图和Warnier图;
-
数据结构规范化。
3.2 与用户沟通获取需求的方法
-
访谈:正式访谈、非正式访谈、调查表、情景分析技术;
-
面向数据流自顶向下求精;
-
简易的应用规格说明技术;
-
快速建立软件原型:(1)第四代技术(4GL);(2)可重用的软件构件;(3)形式化规格说明和原型环境。
3.3 分析建模与规格说明
3.3.1 分析建模
需求分析过程应该建立3种模型:数据模型、功能模型、行为模型。
-
数据字典是分析模型的核心;
-
实体-联系图(ER图)用于建立数据模型;
-
数据流图是建立功能模型的基础;
-
状态转换图是行为建模的基础。
3.4 实体-联系图
数据模型中包含3种相互关联的信息:数据对象、数据对象的属性、数据对象彼此间相互连接的关系。
3.5 状态转换图
3.5.1 状态
状态图分类:
-
表示系统循环运行过程,通常不关心循环是怎样启动的;
-
表示系统单程生命期,需要标明初始状态和最终状态。
3.5.2 事件
事件就是引起系统做动作或(和)转换状态的控制信息。
3.5.3 符号
(具体符号结合教材图形记忆,核心掌握状态、事件、转换的表示方法)
3.6 其他图形工具
-
3.6.1 层次方框图;
-
3.6.2 Warnier图;
-
3.6.3 IPO图。
3.7 验证软件需求(重点)
3.7.1 验证软件需求的正确性(4个方面)
-
一致性:需求之间无矛盾;
-
完整性:无遗漏的需求;
-
现实性:需求在现有技术条件下可实现;
-
有效性:需求符合用户实际需求。
第5章 总体设计
5.1 设计过程
总体设计由两个主要阶段组成:
-
系统设计阶段(确定系统的具体实现方案):设想供选择的方案、选取合理的方案、推荐最佳方案;
-
结构设计阶段(确定软件结构):功能分解、设计软件结构、设计数据库、制定测试文档、书写文档、审查和复查。
5.2 设计原理
5.2.1 模块化
模块化的作用:
-
采用模块化原理可以使软件结构清晰,不仅容易设计也容易阅读和理解;
-
模块化使软件容易测试和调试,因而有助于提高软件的可靠性;
-
模块化能够提高软件的可修改性;
-
模块化也有助于软件开发工程的组织管理。
5.2.2 抽象
抽象是忽略事物细节,只关注核心本质,将复杂问题简化,逐步细化的设计思想。
5.2.3 逐步求精
将抽象的总体设计逐步细化为具体的、可实现的细节设计,分层次、分步骤推进。
5.2.4 信息隐藏和局部化
-
信息隐藏:模块内部的实现细节对其他模块隐藏,仅通过接口交互;
-
局部化:将相关的数据和操作集中在一个模块内,减少模块间的关联。
5.2.5 模块独立
模块独立是设计的核心目标,衡量指标:内聚(模块内部联系紧密程度)、耦合(模块之间关联紧密程度)。
耦合优先级:尽量使用数据耦合,少用控制耦合和特征耦合,限制公共环境耦合的范围,完全不用内容耦合。
七种内聚的优劣排序(从高到低):
-
高内聚:功能内聚、顺序内聚;
-
中内聚:通信内聚、过程内聚;
-
低内聚:时间内聚、逻辑内聚、偶然内聚。
5.3 启发规则(7条)
-
改进软件结构,提高模块独立性;
-
模块规模应该适中;
-
深度、宽度、扇出和扇入都应适当;
-
模块的作用域应该在控制域之内;
-
力争降低模块接口的复杂程度;
-
设计单入口单出口的模块;
-
模块功能应该可以预测。
5.4 描绘软件结构的图形工具
5.4.1 层次图和HIPO图
-
层次图(H图):用来描绘软件的层次结构,很适于在自顶向下设计软件的过程中使用;
-
HIPO图:在层次图基础上,增加输入-处理-输出(IPO)描述,更完整地展示模块功能。
5.4.2 结构图
清晰展示模块之间的调用关系、参数传递,以及模块的控制流。
5.5 面向数据流的设计方法
结构化设计方法(简称SD方法),即基于数据流的设计方法,把信息流映射成软件结构,信息流的类型决定了映射的方法。
信息流的两种类型:变换流、事务流。
第6章 详细设计
6.1 结构程序设计
-
经典的结构程序设计:只允许使用顺序、IF-THEN-ELSE型分支和DO-WHILE型循环这3种基本控制结构;
-
扩展的结构程序设计:除上述3种基本控制结构外,还允许使用DO-CASE型多分支结构和DO-UNTIL型循环结构;
-
修正的结构程序设计:再加上允许使用LEAVE(或BREAK)结构。
6.2 人机界面设计
6.2.1 设计问题
设计人机界面过程中会遇到的4个问题:
-
系统响应时间:关注响应长度和易变性;
-
用户帮助设施:集成的帮助设施、附加的帮助设施;
-
出错信息处理;
-
命令交互。
6.2.3 人机界面设计指南
-
一般交互指南;
-
信息显示指南;
-
数据输入指南。
6.3 过程设计的工具
6.3.1 程序流程图(程序框图)
主要缺点:
-
本质上不是逐步求精的好工具,诱使程序员过早考虑控制流程,忽略全局结构;
-
用箭头代表控制流,可随意转移控制,违背结构程序设计精神;
-
不易表示数据结构。
6.3.2 盒图(N-S图)
核心特点:
-
功能域明确;
-
不可能任意转移控制;
-
易确定局部和全程数据的作用域;
-
易表现嵌套关系和模块层次结构。
6.3.3 PAD图
用二维树形结构表示程序控制流,易转换为程序代码,主要优点:
-
设计出的程序必然是结构化程序;
-
程序结构清晰,易读、易懂、易记;
-
可自动转换为高级语言源程序;
-
既可表示程序逻辑,也可描绘数据结构;
-
支持自顶向下、逐步求精方法。
6.3.4 判定表
优势:能清晰表示复杂的条件组合与应做动作之间的对应关系;
缺点:含义不直观,需学习理解;数据元素值多于两个时,简洁性下降。
6.3.5 判定树
优势:形式简单,含义直观,易掌握使用;
缺点:简洁性不如判定表,数据元素值易重复;分枝次序影响简洁程度。
6.3.6 过程设计语言(伪码,PDL)
基本控制结构:简单陈述句结构、判定结构(IF_THEN_ELSE或CASE_OF)、选择结构(WHILE_DO或REPEAT_UNTIL)。
优点:可作为注释插入源程序,保持文档与程序一致性;易书写编辑;可自动生成代码;
缺点:不如图形工具直观,复杂条件组合描述不如判定表清晰。
6.4 面向数据结构的设计方法
最终目标:得出对程序处理过程的描述。
-
6.4.1 Jackson图:描述数据结构,三种基本结构——顺序(A由B、C、D顺序组成)、选择(A是B、C、D中的某一个)、重复(A由B出现N次(N≥0)组成);
-
6.4.2 改进的Jackson图:优化基本Jackson图的不足,增强表达能力;
-
6.4.3 Jackson方法:基于Jackson图,将数据结构映射为程序结构。
6.5 程序复杂程度的定量度量
6.5.1 McCabe方法
-
流图(程序图):简化的程序流程图,只关注控制流,不关注数据;
-
计算环形复杂度的3种方法:
-
V(G = 流图中的区域数;
-
V(G = E - N + 2(E是边数,N是结点数);
-
V(G = P + 1(P是判定结点的数目)。
-
6.5.2 Halstead方法
核心定义与公式:
-
N1:程序中运算符出现的总次数;N2:操作数出现的总次数;程序长度N = N1 + N2;
-
n1:不同运算符(含关键字)的个数;n2:不同操作数(变量和常数)的个数;
-
预测程序长度: H=n1log2n1+n2log2n2H = n_1 \log_2 n_1 + n_2 \log_2 n_2H=n1log2n1+n2log2n2 ;
-
预测程序错误个数: E=Nlog2(n1+n2)/3000E = N \log_2 (n_1+n_2)/3000E=Nlog2(n1+n2)/3000 。
第7章 实现
编码和测试统称为实现,是将设计方案转化为可运行软件的过程。
7.1 编码
7.1.1 选择程序设计语言
主要实用标准(7点):
-
系统用户的要求;
-
可以使用的编译程序;
-
可以得到的软件工具;
-
工程规模;
-
程序员的知识;
-
软件可移植性要求;
-
软件的应用领域。
7.1.2 编码风格
-
程序内部的文档:恰当的标识符、适当的注解、程序的视觉组织;
-
数据说明:规范、清晰,便于理解;
-
语句构造:简洁、规范,符合结构程序设计要求;
-
输入输出:友好、直观,便于用户操作;
-
效率:关注程序运行时间、存储器效率、输入输出效率。
7.2 软件测试基础
7.2.1 软件测试的目标(3点)
-
测试是为了发现程序中的错误而执行程序的过程;
-
好的测试方案是极可能发现迄今为止尚未发现的错误的测试方案;
-
成功的测试是发现了至今为止尚未发现的错误的测试。
7.2.3 测试方法(两大核心)
-
黑盒测试(功能测试):
-
把程序看作一个黑盒子,完全不考虑内部结构和处理过程;
-
在程序接口进行测试,关注输入输出是否符合需求。
-
-
白盒测试(结构测试):
-
把程序看成透明的盒子,测试者完全知道结构和处理算法;
-
按照程序内部逻辑测试,检测主要执行通路是否正常。
-
7.2.4 测试步骤(5步,从局部到整体)
-
模块测试(单元测试):
-
保证每个模块作为一个单元能正确运行;
-
发现的往往是编码和详细设计的错误。
-
-
子系统测试:
-
把经过单元测试的模块组成子系统测试;
-
着重测试模块的接口。
-
-
系统测试:
-
把经过测试的子系统装配成完整系统测试;
-
发现的往往是软件设计和需求说明中的错误;
-
子系统测试和系统测试统称集成测试(兼具检测和组装功能)。
-
-
验收测试(确认测试):
-
把软件系统作为单一实体测试,用户积极参与,使用实际数据;
-
发现的往往是系统需求说明书中的错误。
-
-
平行运行:新系统与旧系统同时运行,对比结果,确保新系统可靠。
7.2.5 测试阶段的信息流
输入信息两类:
-
软件配置:需求说明书、设计说明书、源程序清单等;
-
测试配置:测试计划、测试方案。
7.3 单元测试
单元测试集中检测单个模块,与编码属于同一阶段,可采用人工测试和计算机测试,主要使用白盒测试技术,多个模块可并行测试。
7.3.1 测试重点(5点)
-
模块接口:参数传递、数据输入输出是否正确;
-
局部数据结构:数据定义、初始化、赋值是否正确;
-
重要的执行通路:核心逻辑是否正确;
-
出错处理通路:出错处理是否合理、有效;
-
边界条件:临界值、边界情况是否处理正确(易出错点)。
7.3.2 代码审查
由审查小组正式进行,一次审查可发现多个错误,减少系统验证总工作量。
7.3.3 计算机测试
-
驱动程序:“主程序”,接收测试数据,传送给被测试模块,输出结果;
-
存根程序:代替被测试模块调用的模块,模拟接口,完成简单数据操作并返回控制。
7.4 集成测试
集成测试是测试和组装软件的系统化技术,主要目标是发现与接口有关的问题。
模块组装方法:自顶向下集成、自底向上集成(教材详细介绍,结合流程记忆)。
7.4.3 不同集成测试策略的比较
混合策略:改进的自顶向下测试方法、混合法(结合自顶向下和自底向上的优势)。
7.4.4 回归测试
修改软件后,重新测试相关模块,确保修改不会引入新错误,也不会影响原有功能的正确性。
7.5 确认测试
确认测试也称为验收测试,目标是验证软件的有效性(是否符合用户实际需求)。
7.5.3 Alpha和Beta测试
-
Alpha测试:在受控的环境中(开发方内部)进行;
-
Beta测试:在开发者不能控制的环境中(用户实际使用场景)进行,属于“真实”应用测试。
确认测试的主要内容(10点):
-
接口测试;
-
路径测试;
-
功能测试;
-
健壮性测试;
-
性能测试;
-
用户界面测试;
-
信息安全测试;
-
压力测试;
-
可靠性测试;
-
安装/反安装测试。
7.6 白盒测试技术
7.6.1 逻辑覆盖(从弱到强)
-
语句覆盖:覆盖所有可执行语句(最弱);
-
判定覆盖:覆盖所有判定的真假分支(比语句覆盖强,仍不充分);
-
条件覆盖:覆盖所有判定中每个条件的真假值(判定覆盖与条件覆盖无必然包含关系);
-
判定/条件覆盖:同时满足判定覆盖和条件覆盖(不一定比条件覆盖更强);
-
条件组合覆盖:覆盖所有条件的所有组合(不一定覆盖所有路径);
-
点覆盖:与语句覆盖标准相同;
-
边覆盖:与判定覆盖一致;
-
路径覆盖:覆盖程序中所有可能的执行路径(最强)。
7.6.2 控制结构测试覆盖
-
基本路径测试(Tom McCabe提出):
-
首先计算程序的环形复杂度;
-
以复杂度为指南定义执行路径的基本集合;
-
从基本集合导出测试用例,保证每条语句至少执行一次,每个条件取真假值。
-
-
条件测试:针对判定中的条件,设计测试用例覆盖条件的各种组合;
-
循环测试:专注于循环结构,测试循环的边界值、循环次数等,包括简单循环、串接循环、嵌套循环。
7.7 黑盒测试技术
-
7.7.1 等价划分:将输入数据划分为若干等价类,每个等价类选一个测试用例,减少测试工作量;
-
7.7.2 边界值分析:重点测试等价类的边界值(易出错点),补充等价划分的不足;
-
7.7.3 错误推测:基于经验和直觉,推测可能出现的错误,设计测试用例。
7.9 软件可靠性
7.9.1 基本概念
-
软件可靠性:程序在给定的时间间隔内,按照规格说明书的规定成功地运行的概率;
-
软件的可用性:程序在给定的时间点,按照规格说明书的规定,成功地运行的概率。
第8章 维护
软件工程的目的是提高软件的可维护性,减少维护工作量,降低系统总成本。
8.1 软件维护的定义
软件维护:在软件已经交付使用之后,为了改正错误或满足新的需要而修改软件的过程,可分为4项活动:
-
改正性维护:修改软件中的错误(最基础的维护);
-
适应性维护:适应硬件、软件环境变化而进行的修改;
-
完善性维护:为满足用户新的功能、性能需求而进行的修改(占比最高);
-
预防性维护:为防止未来出现问题而进行的提前修改(占比最低)。
8.2 软件维护的特点
-
8.2.1 结构化维护与非结构化维护差别巨大:结构化开发的软件,维护更高效、成本更低;
-
8.2.2 维护的代价高昂:维护成本通常高于开发成本,且随时间增长;
-
8.2.3 维护的问题很多:维护难度大、周期长,易引入新错误。
8.3 软件维护过程(5步)
-
维护组织:明确维护职责和分工;
-
维护报告:记录维护请求、原因、方案;
-
维护的事件流:按照流程处理维护请求;
-
保存维护记录:便于追溯和改进;
-
评价维护活动:总结经验,优化维护流程。
8.4 软件的可维护性
决定软件可维护性的7个主要因素:
-
可理解性:软件易于理解;
-
可测试性:易于设计测试用例,进行测试;
-
可修改性:易于修改,且不引入新错误;
-
可靠性:修改后仍能稳定运行;
-
可移植性:易于移植到不同环境;
-
可使用性:用户易于操作和维护;
-
效率:维护后软件性能不下降。
第10章 面向对象分析
10.1 面向对象分析的基本过程
面向对象分析:抽取和整理用户需求并建立问题域精确模型的过程,核心是建立3个子模型,其中对象模型最基本、最重要、最核心。
面向对象分析的三个核心:
-
静态结构(对象模型);
-
交互次序(动态模型);
-
数据变换(功能模型)。
复杂问题的对象模型的5个层次:(结合教材,从抽象到具体逐步构建)
面向对象分析的过程(7步):
-
寻找类与对象;
-
识别结构;
-
识别主题;
-
定义属性;
-
建立动态模型;
-
建立功能模型;
-
定义服务。
面向对象分析的三个关键环节:
一是精准识别问题域中的类与对象,奠定对象模型的基础;二是明确对象间的交互关系与动态行为,构建动态模型与功能模型;三是梳理类的属性与服务,完善整个分析模型,为后续面向对象设计提供清晰、完整的依据。
这三个关键环节相互关联、层层递进,贯穿面向对象分析的全过程,只有将三者有机结合,才能构建出贴合问题域、满足用户需求的分析模型,为后续面向对象设计阶段的类设计、接口设计等工作提供坚实支撑。
需要注意的是,面向对象分析并非孤立的步骤,而是与软件生命周期的其他阶段紧密衔接,既要基于需求分析阶段的成果,又要为后续面向对象设计阶段的类结构优化、接口定义、交互设计等工作提供明确指引,确保整个软件开发过程的连贯性和一致性。
综上,面向对象分析以问题域为核心,通过七步流程构建对象、动态、功能三大子模型,聚焦类与对象的识别、结构梳理及服务定义,三个关键环节层层递进,同时衔接软件生命周期各阶段,为面向对象设计提供可靠依据,是保障软件开发连贯性和需求贴合度的重要环节。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)