软件工程-概念型总结
第一章 软件工程学概述
软件发展的三个阶段
- 程序设计 - 50到60年代
- 程序系统 - 60到70年代
- 软件工程 - 70年代以后
软件的概念
软件 = 程序+文档+数据
什么是软件危机?
是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。
包括两个方面:
- 如何开发软件,以满足对软件日益增长的需求
- 如何维护数量不断膨胀的已有软件
软件危机的典型表现
- 对软件开发成本和进度的估计常常不准确
- 用户对“已完成”软件系统不满意的现象常发生
- 软件产品的质量靠不住
- 软件不可维护
- 软件没有适当的文档资料
- 成本逐年上升
- 开发生产率跟不上计算机应用普及深入的速度
软件危机的产生原因
主观原因:
- 忽视需求分析
- 轻视软件维护
- 没有认识到程序知识软件的一部分
客观原因: - 与软件本身的特点有关,软件是逻辑部件不是物理部件
- 和软件开发与维护的方法不正确
- 软件规模庞大,程序复杂性随规模增加指数上升
消除软件危机的途径
- 首先对软件有一个正确的认识
- 推广在实践中总结的技术和方法,并探索更好的
- 既要有技术措施(方法和工具),又要有必要的组织管理措施
什么是软件工程?
软件工程是1️⃣把系统的、规范的、可度量的途径应用于软件开发、运行和维护过程,也就是把工程应用于软件;2️⃣研究1️⃣中提到的途径。
软件工程的特征
- 软件工程关注于大型程序的构造
- 软件工程的中心课题是控制复杂性
- 软件经常变化
- 开发软件的效率非常重要
- 和谐地合作是开发软件的关键
- 软件必须有效地支持它的用户
- 在软件工程领域通常是具有一种文化背景的人替具有另外一种文化背景的人创造产品
正式提出“软件工程”是什么时候?
在1968年西德召开的国际会议上正式提出
软件工程的7条基本原理
- 用分阶段的生命周期计划严格管理
- 坚持进行阶段评审
- 实行严格的产品控制
- 采用现代程序设计技术
- 结果应能清楚地审查
- 开发小组的人员应该少而精
- 承认不断改进软件工程实践的必要性
软件工程方法学的三要素
- 方法
- 工具
- 过程
软件工程方法学的划分
- 传统方法学(生命周期方法学/结构化范性)
- 采用结构化技术
- 强调自顶向下
- 面向对象方法学
- 迭代
软件生命周期
- 软件定义
- 问题定义
- 要解决什么问题
- 可行性研究
- 对于上一个阶段所确定的问题想出解决方法
- 需求分析
- 确定目标系统需要什么功能
- 问题定义
- 软件开发
- 总体设计(概要设计)
- 怎么样实现目标系统
- 详细设计
- 怎么具体的实现目标系统
- 编码和单元测试
- 写出容易理解、容易维护的模块
- 综合测试
- 是软件达到预定的要求
- 总体设计(概要设计)
- 运行维护
- 延长软件的生命周期
软件过程模型的优缺点
瀑布模型
- 特点
- 阶段间具有顺序性和依赖性
- 推迟实现的观点
- 质量保证的观点
- 是“文档驱动”的模型
- 优点
- 可强迫开发人员采用规范的方法
- 严格地规定了每个阶段必须提交的文档
- 要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证
- 缺点
- 只能通过文档了解产品,不经过实践的需求是不切实际的
- 适用于
- 需求是预知的
- 软件实现方法是成熟的
- 项目周期较短
快速原型模型
- 特点
- 不带反馈环,线性顺序进行的
- 本质是“快速”,尽可能快地建造出原型系统,以加速软件开发过程,节约成本
- 优点
- 开发的软件产品通常满足用户需求
- 软件产品开发基本是线性过程
- 缺点
- 准确原型设计困难
- 原型理解可能不同
- 不利于开发人员创新
- 三类原型模型
- 探索型原型
- 用于开发的需求分析阶段
- 实验型原型
- 主要用于设计阶段
- 演化型原型
- 用于及早向用户提交一个原型系统
- 探索型原型
- 运用方式
- 抛弃策略
- 探索型和实验型采用此策略
- 附加策略
- 演化型快速原型采用此策略
- 抛弃策略
增量模型
- 优点
- 短时间内可提交完成部分功能
- 逐渐增加产品功能,用户适应产品块
- 缺点
- 软件体系结构必须是开放的
- 模型本身是自相矛盾的,整体——独立构件
- 不同的构件并行地构建有可能加快工程进度,但可能有无法集成到一起的风险
- 适用于
- 需求经常改变的软件开发过程
- 如果在项目既定的商业要求期限之前不可能找到足够的开发人员,在这种情况下,增量模型显得特别有用
螺旋模型
- 特点
- 使用原型及其他方法来尽量降低风险。把它看作在每个阶段之前都增加了风险分析过程的快速原型模型
- 优点
- 主要优势在于它是风险驱动的
- 对可选方案和约束条件的强调有利于已有软件的重用,也有助于把软件质量作为软件开发的一个重要目标
- 减少了过多测试或测试不足所带来的风险
- 缺点
- 采用螺旋模型需要具有相当丰富的风险评估经验和专门知识,在风险较大的项目开发中,如果未能够及时标识风险,势必造成重大损失
- 过多的迭代次数会增加开发成本,延迟提交时间
- 适用于
- 特别适用于庞大、复杂并具有高风险的系统
- 适用于内部开发的大规模软件项目
喷泉模型
- 特点
- 是典型的面向对象生命周期模型
- 迭代和无缝
- 优点
- 该模型的各个阶段没有明显的界限,开发人员可以同步进行开发
- 多次反复地增加或明确目标系统,而不是本质性的改动,降低错误的可能性
- 缺点
- 由于喷泉模型在各个开发阶段是重叠的,因此在开发过程中需要大量的开发人员,不利于项目的管理
- 要求严格管理文档,使得审核的难度加大,尤其是面对可能随时加入各种信息、需求与资料的情况
- 适用于
- 适用于面向对象的软件开发过程
微软过程
- 特点
- 每一个生命周期发布一个递进的版本,各生命周期持续快速地迭代循环
- 优点
- 综合了Rational统一过程和敏捷过程的优点
- 缺点
- 对方法、工具和产品等方面不够全面
Rational统一模型(RUP)
- RUP是一种迭代的,以架构为中心的,用例驱动的软件开发方法。
- RUP是一种具有明确定义和结构的软件工程过程。
- RUP还是一个过程产品,提供了可定制的软件工程的过程框架。
- RUP被广泛应用在不同工业领域中的不同企业中。
敏捷过程与极限编程
- 敏捷过程中最富盛名的一个
- 广泛适用于需求模糊且经常改变的场合
- 使得敏捷过程能够较好地适应商业竞争环境下对小型项目提出的有限资源和有限开发时间的约束
第二章 可行性研究
可行性的几个方面
- 技术可行性
- 经济可行性
- 操作可行性
必要时还有从法律、社会效益等方面。
可行性研究的过程
- 复查系统规模和目标
- 研究目前正在使用的系统
- 导出新系统的高层逻辑模型
- 进一步定义问题
- 导出和评价供选择的解法
- 推荐行动方针
- 草拟开发计划
- 书写文档提交审查
系统流程图
数据流图(DFD)的用途
- 利用它作为交流信息的工具
- 作为分析和设计的工具
- 也适用于需求分析阶段
数据流图的符号表示
数据字典(DD)的组成
- 数据流
- 数据流分量(即数据元素)
- 数据存储
- 处理
数据字典的用途
- 作为分析阶段的工具
- 是开发数据库的第一步
数据元素组成数据的方式
- 顺序
- 选择
- 重复
第三章 需求分析
SA方法的三大模型
- 功能模型
- DFD图表示
- 数据模型
- E-R图表示
- 行为模型
- 状态转换表示
需求书写的常用方法
- 自然语言
- 结构化自然语言
- 图形化表示法
- 数学规格说明书
需求分析的任务
- 确定对系统的综合要求
- 功能需求
- 非功能需求
- 可靠性和可用性
- 出错处理需求
- 接口需求
- 约束
- 逆向需求
- 将来可能提出的要求
- 分析系统的数据要求
- 建立数据模型
- ER图
- 描绘数据结构
- 层次方框图和Warnier图
- 数据结构规范化
- 建立数据模型
- 导出系统的逻辑模型
- 导出系统的详细的逻辑模型,通常用数据流图、实体-联系图、状态转换图、数据字典和主要的处理算法描述这个逻辑模型
- 修正系统开发计划
- 根据在分析过程中获得的对系统的更深入更具体的了解,可以比较准确地估计系统的成本和进度,修正以前制定的开发计划
与用户沟通获取需求的方法
- 访谈
- 正式访谈
- 非正式访谈
- 调查表
- 情景分析技术
- 面向数据流自顶向下求精
- 分析追踪数据流图
- 用户复查
- 简易的应用规格说明技术
- 快速建立软件原型
- 最准确、最有效、最强大的需求分析技术
- 快速建立起来的旨在演示目标系统主要功能的可运行的程序
- 要点是,它应该实现用户看得见的功能,省略目标系统的“隐含”功能
分析建模与规格说明
- 需要写出软件需求规格说明书
实体-联系图
- 描绘数据对象及数据对象之间的关系,是用于建立数据模型的图形
- ER图中3种互相关联的信息
- 数据对象
- 是对软件必须理解的复合信息的抽象。复合信息是指具有一列不同性质或属性的事物,仅有单个值的事物不是数据对象
- 矩形框表示
- 属性
- 定义了数据对象的性质。必须把一个或多个属性定义为“标识符” 。用标识符属性作为“关键字,(通常简称为“键”)。根据对问题的理解来确定特定数据对象的合适的属性。
- 用椭圆形/圆角矩形表示
- 联系
- 数据对象彼此之间相互连接的方式称为联系,也称为关系
- 一对一联系(1∶1)
- 一对多联系(1∶N)
- 多对多联系(M∶N)
- 联系也可能有属性
- 用菱形框表示
- 数据对象
- ER图的优点
- 比较接近人的习惯思维方式
- 用简单的图形符号表达系统分析员对问题域的理解,用户也容易理-解,可以作为用户与分析员之间有效的交流工具。
从那些方面验证软件需求的正确性
- 一致性
- 完整性
- 现实性
- 有效性
第五章 总体设计
总体设计的两个阶段(工程角度)
- 系统设计阶段
- 确定系统的具体实现步骤
- 结构设计阶段
- 确定软件结构
从技术的角度
- 传统的结构化方法
- 体系结构设计
- 数据设计
- 接口设计
- 过程设计
- 面向对象方法
- 体系结构设计
- 类设计/数据设计
- 结构设计
- 构件级设计
典型的总体设计过程的9个步骤
- 设想供选择的方案
- 选取合理的方案
- 推荐最佳方案
- 功能分解
- 设计软件结构
- 设计数据库
- 制定测试计划
- 书写文档
- 审查和复审
设计原理
- 模块化
- 抽象
- 逐步求精
- 信息隐藏和局部化
- 模块独立
模块化
- 作用
- 使软件结构清晰,不仅容易设计也容易阅读和理解。
- 使软件容易测试和调试,有助于提高软件的可靠性。
- 提高软件的可修改性。
- 有助于软件开发工程的组织管理。
- 5条标准
- 模块可分解性
- 模块可组装性
- 模块可理解性
- 模块连续性
- 模块保护性
抽象
- 人类在认识复杂现象的过程中使用的最强有力的思维工具
逐步求精
- 人类解决复杂问题时采用的基本方法
模块独立
- 模块的独立程度可以由两个定性标准的度量
- 内聚
- 耦合
耦合
- 是对一个软件结构内不同模块之间互连程度的度量
- 是影响软件复杂程度的一个重要因素
设计原则
- 尽量使用数据耦合
- 少用控制耦合和特征耦合
- 限制公共环境耦合的范围
- 完全不用内容耦合
耦合程度的度量
- 非直接耦合/完全独立
- 数据耦合
- 控制耦合
- 特征耦合
- 公共环境耦合
- 内容耦合
- 最高程度的耦合是内容耦合
内聚
- 标志一个模块内各个元素彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展。简单地说,理想内聚的模块只做一件事情
内聚程度的度量
- 偶然内聚
- 逻辑内聚
- 时间内聚
- 过程内聚
- 通信内聚
- 顺序内聚
- 功能内聚
设计时最佳 高内聚低耦合
启发规则
- 改进软件结构提高模块独立性
- 模块规模应该适中
- 深度、宽度、扇出和扇入都应适当
- 力求做到顶层扇出较高,中间层扇出较少,底层模块高扇入
- 模块的作用域应该在控制之内
- 力争降低模块接口的复杂程度
- 模块接口复杂是软件发生错误的一个主要原因
- 设计单入口单出口的模块
- 模块功能应该可以预测
描绘软件结构的图形工具
层次图(H图)
- 描绘软件的层次结构。很适于在自顶向下设计软件的过程中使用
层次图和层次方框图的对比
HIPO图
- 层次图+输入/处理/输出图
- 美国IBM公司发明
- 为了能使HIPO图具有可追踪性,在H图(层次图)里除了最顶层的方框之外,每个方框都加了编号
结构图
- 方框代表一个模块
- 方框之间的直线表示模块的调用关系
- 尾部是空心圆箭头表示传递的是数据
- 尾部实心圆箭头表示传递的是控制信息
面向数据流的设计方法
- 目标是给出设计软件结构的一个系统化的途径
- 面向数据流的设计方法把信息流映射成软件结构,信息流的类型决定了映射方法,信息流以下方法
- 变换流
- 事务流
- 结构化设计方法(SD),也是基于数据流的设计方法
第六章 详细设计
表达工具
- 程序流程图
- PAD图
- 盒图
- 判定表
- 判定树
- PDL语言
人机介面设计的三条黄金规则
- 置用户于规则之下
- 减少用户的记忆负担
- 保持界面一致
程序流程图(程序框图)
- 对控制流程的描绘很直观
- 缺点
- 不是逐步求精的好工具,它诱使程序员过早地考虑程序的控制流程,而不去考虑程序的全局结构。
- 用箭头代表控制流,因此程序员不受任何约束,可以完全不顾结构程序设计的精神,随意转移控制。
- 程序流程图不易表示数据结构。
盒图(N-S图)
- 特点
- 功能域明确。
- 不可能任意转移控制。
- 很容易确定局部和全程数据的作用域。
- 很容易表现嵌套关系,也可以表示模块的层次结构。
PAD图(问题分析图)
- 用二维树形结构的图来表示程序的控制流
- 优点
- 使用PAD符号设计出来的程序必然是结构化程序。
- 程序结构十分清晰。
- 逻辑易读、易懂、易记。
- 容易将PAD图转换成高级语言源程序,可用软件工具自动完成。
- 即可表示程序逻辑,也可描绘数据结构。
- 支持自顶向下、逐步求精方法的使用。
判定表
-
由4部分组成
-
优点
- 能够清晰地表示复杂的条件组合与应做的动作之间的对应关系
-
缺点
- 含义不就一眼看出来,需要有一个简短的学习过程。
- 当数据元素的值多于两个时,判定表的简洁程度也将下降。
判定树
- 判定树是判定表的变种,能清晰地表示复杂的条件组合与应做的动作之间的对应关系
- 优点
- 形式简单,一眼可看出其含义,易于掌握和使用
- 缺点
- 简洁性不如判定表,数据元素的同一个值要重复写多遍,越接近树的叶端重复次数越多。
- 分枝的次序可能对最终画出的判定树的简洁程度有较大影响。
过程设计语言(PDL/伪码)
- 用正文形式表示数据和处理过程的设计工具
- 有严格的关键字外部语法,用于定义控制结构和数据结构
- PDL表示实际操作和条件的内部语法通常又是灵活自由的,可以适应各种工程项目的需要
面向数据结构设计的设计方法
- 最终目标:是得出对程序处理过程的描述
Jackson图
改进Jackson图
Jackson图与层次图的比较
程序复杂程度的定量度量
- 可估算出软件中的错误的数量
- 软件开发需要的工作量
- 结果可以比较两个设计/算法的优劣
- 作为模块规模的精确限度
常用方法
- McCabe
- Halstead
McCabe方法
计算环形复杂度(V(G))的方法
- 3种方法
- V(G)=流图中的区域数
- V(G)=E-N+2
- E是流图中的边数,N是结点数
- V(G)=P+1
- P是流图中判定结点的数目
环形复杂度的用途
- 定量度量程序内分支数或循环个数,即程序结构的复杂程度;
- 定量度量测试难度;
- 能对软件最终的可靠性给出某种预测。
- 实践表明,模块规模以V(G)≤10为宜。
Halstead方法
-
根据程序中运算符和操作数的总数来度量程序的复杂程度。
-
令N1为程序中运算符出现的总次数,N2为操作数出现的总次数,程序长度N定义为:
- N=N1+N2
-
程序中使用的不同运算符(包括关键字)的个n1,以及不同操作数(变量和常数)的个数n2。预测程序长度的公式如下:
-
预测程序中包含错误的个数的公式如下:
第七章 实现
通常把编码和测试同称实现
编码
- 就是把软件设计结果翻译成用某种程序设计语言书写的程序
编码语言选择规则
- 系统用户要求
- 可以使用的编译程序
- 可以得到的软件工具
- 工程规模
- 程序员的知识
- 软件可移植性要求
- 软件的应用领域
编码风格规则
- 程序内部的文档
- 恰当的标识符
- 适当的注视
- 程序的视觉组织
- 数据说明
- 语句结构
- 输入输出
- 效率
测试的定义
- 为了发现程序中的错误而执行程序的过程
软件测试准则
- 所有测试都应该追溯用户需求
- 应该远在测试开始之前写出测试计划
- 把Pareto原理应用到软件测试中
- 从小规模测试开始再到大规模
- 穷举测试是不可能的
- 为达最佳效果,应由独立第三方机构测试
测试方法
- 黑盒测试
- 功能测试,程序接口进行测试
- 完全不考虑内部结构和处理过程
- 只检查程序能否按规格说明书正常使用
- 白盒测试
- 结构测试,程序内部的逻辑测试
- 测试者要完全知道程序的结构和处理算法
测试步骤
- 模块测试
- 首选白盒,白盒为主、黑盒为辅
- 子系统测试
- 系统测试(集成测试)
- 验收测试
- 发现需求说明书的错误
- 平行运行
测试的两个临时模块
- 驱动模块
- 桩模块
测试信息流
- 软件配置
- 需求说明书、设计说明书和源程序清单等
- 测试配置
- 测试计划
- 测试方案
单元测试的重点
- 模块接口
- 局部数据结构
- 重要的执行通路
- 出错处理通路
- 边界条件
代码审查
- 一种有效的程序验证技术
- 一般由4人组成
- 组长(没有直接参与这项工程)
- 程序的设计者
- 程序的编写者
- 程序的测试者
- 一般先研究设计说明书,可以一次发现多个错误
计算机测试
- 一般发现错误要先改正才能继续执行
集成测试
- 是测试和组装软件的系统化技术
- 目标是发现与接口有关的问题
可分类两类
- 非渐增式子
- 渐增式
- 自顶向下
- 自底向上
确认测试(验收测试)
- 目标是验证软件的有效性
Alpha和Beta测试
- Alpha测试是在受控制的环境下进行的
- Beta测试是软件在开发者不能控制的环境中“真实”应用
测试用例
- 测试数据
- 预期结果
白盒测试(结构测试)
典型技术
- 逻辑覆盖
- 控制结构测试
- 基本测试路径
- 确定线性独立路径
- 条件测试
- 循环测试
- 基本测试路径
逻辑覆盖
- 从语句角度分析
- 语句覆盖
- 至少每个语句执行一次
- 判定覆盖(分支覆盖)
- 语句、判定可能结果、分支都至少执行一次
- 只关心判定表达式的值
- 条件覆盖
- 不仅每个语句执行一次,判定条件都取各种可能结果
- 通常比判定覆盖强
- 判定/条件覆盖
- 判定覆盖不一定包含条件覆盖
- 条件覆盖不一定包含判定覆盖
- 条件组合覆盖
- 每个组合至少执行一次
- 满足条件组合覆盖的数据不一定使每条路径都执行到
- 语句覆盖
- 从流图角度分析
- 点覆盖
- 与语句覆盖标准相同
- 边覆盖
- 通常与判定覆盖一致
- 路径覆盖
- 点覆盖
黑盒测试(功能测试)
黑盒测试力求发现的错误
- 功能错误
- 界面错误
- 数据结构错误或外部数据库访问错误
- 性能错误
- 初始化和终止错误
典型技术
- 等价划分
- 边界值划分
- 一般取值为 刚好等于、稍小于、稍大于边界值
- 错误推测
- 很大程度靠直觉和经验进行
等价类划分的规则
- 如果规定了输入值的范围,则可划分出一个有效的等价类(输入值在此范围内),两个无效的等价类(输入值小于最小值或大于最大值);
- 如果规定了输入数据的个数,则类似地也可划分出一个有效的等价类和两个无效的等价类;
- 如果规定了输入数据的一组值,而且程序对不同输入值做不同处理,则每个允许的输入值是一个有效的等价类,此外还有一个无效的等价类(任一个不允许的输入值);
- 如果规定了输入数据必须遵循的规则,则可以划分出一个有效的等价类(符合规则)和若干个无效的等价类(从各种不同角度违反规则);
- 如果规定了输入数据为整型,则可以划分出正整数、零和负整数等3个有效类;
- 如果程序的处理对象是表格,则应该使用空表,以及含一项或多项的表。
测试方案
- 设计一个新的测试方案以尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步骤直到所有有效等价类都被覆盖为止;
- 设计一个新的测试方案,使它覆盖一个而且只覆盖一个尚未被覆盖的无效等价类,重复这一步骤直到所有无效等价类都被覆盖为止。
调试
- 调试是在测试发现错误之后排除错误的过程。
- 调试就是把症状和原因联系起来的尚未被人深入认识的智力过程。
调试途径
- 蛮干法
- 回溯法
- 原因排除法
- 对分查找法
- 归纳法
- 演绎法
软件可靠性:
- 程序在给定的时间间隔内,按照规格说明书的规定成功地运行的概率。
软件的可用性:
- 程序在给定的时间点,按照规格说明书的规定,成功地运行的概率。
第八章 维护
维护的4项活动
- 改正性维护
- 17%~21%
- 适应性维护
- 18%~25%
- 完善性维护
- 50%~66%
- 预防性维护
- 4%左右
软件维护的特点
- 结构化与非结构化维护的差别巨大
- 维护的代价高昂
- 维护的问题多
软件维护过程
- 维护组织
- 维护报告
- 维护事件流
- 保存维护记录
- 评价维护活动
软件的可维护性
- 维护人员理解、改正、改动或改进这个软件的难易程度
决定软件可维护性的因素
- 可理解性
- 可测试性
- 可修改性
- 可移植性
- 可重用性
软件维护的副作用
- 编码副作用
- 数据副作用
- 文档fuzuoy
第十三章 软件项目管理
管理
- 就是通过计划、组织和控制等一系列活动,合理地配置和使用各种资源,以达到既定目标的过程
软件项目规模
- 代码行技术是定量估算软件规模的方法
进度计划管理工具
- 甘特图(Gantt)
- 工程网络图