软件工程复习篇(上):https://developer.aliyun.com/article/1446312
3.5其他图形工具
层次方框图
表示方式:用树形结构的一系列矩阵框描述数据的层次结构
优点:随着层次的逐步惊喜,对数据结构的描绘也越来越详细
Warnier图
表示方式:用树形结构描绘信息的层次结构
优点:可以表明信息的逻辑组织。可以表明某类信息出现的条件或是否重复出现
IPO图
表示方式:是输入、处理、输出图的简称,能够方便地描绘输入数据、对数据的处理和输出数据之间的关系
优点:简略描绘系统主要算法
3.6验证软件需求
从那些方面验证软件需求的正确性
- 一致性:所有需求必须是一致的
- 完整性:需求必须是完整的
- 现实性:指定的需求应该能用现有的硬件而后软件技术实现
- 有效性:必须证明需求是正确有效的
验证软件需求的方法
- 验证需求的一致性:自然语言描述需求、形式化语言描述需求、用软件工具验证
- 验证需求的现实性:参照开发经验
- 验证需求的完整性和有效性:建立软件原型
四、总体设计
4.1设计过程
总体设计又称为概要设计或初步设计
任务:
- 确定系统中每个程序由哪些模块组成以及这些模块相互间的关系
- 划分出物理元素。包括程序、数据库、文档等
设计过程包括系统设计阶段和结构设计阶段
系统设计阶段
- 设想供选择的方案:数据流图出发,将处理分组抛弃行不通分组
- 选取合理的方案:上一步方案中选取低、中、高成本三种方案
- 推荐最佳方案:制定详细实现计划
结构设计阶段
- 功能分解:对数据流图进一步细化,进行功能分解。可以用IPO图等工具描述细化后每个处理的算法
- 设计软件结构:层次图或结构图描绘软件结构。或数据流图导出软件结构
- 设计数据库
- 指定测试文档
- 书写文档
- 审查和复审
4.2设计原理
概念
模块:能够单独命名,由边界元素限定的程序元素的序列,是构成程序的基本构件
模块化:把程序划分为独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足用户的需求
抽象:抽出事物的本质特征而暂时不考虑细节
逐步求精:逐步揭露出底层细节
信息隐藏:指一个模块内包含的信息对于不需要这些信息的模块来说,是不能访问的。主要是指模块的实现细节
局部化:指把一些关系密切的软件元素物理地放得彼此靠近,有助于实现信息隐藏
模块独立
- 模块独立性:是模块化、抽象、信息隐蔽和局部化概念的直接结果
- 模块独立是好设计的关键,设计师决定软件质量的关键环节
- 度量标准:耦合、内聚
耦合
是对一个软件结构内不同模块之间互连程序的度量。
耦合强度取决于模块接口的复杂程度、通过接口的数据等。耦合性越高,模块独立性越弱
耦合分类(低->高):无直接耦合=>数据耦合=>标记耦合(特征耦合)=>控制耦合=>外部耦合=>公共耦合
内聚
用来衡量一个模块内部各个元素彼此结合的紧密程度
内聚分类(低->高):偶然内聚=>逻辑内聚=>时间内聚=>过程内聚=>通信内聚=>顺序内聚=>功能内聚
同其他模块强耦合的模块意味着弱内聚;
软件设计目标:强内聚、低耦合
4.3启发规则
- 改进软件结构提高模块独立性
- 模块规模应该是中
- 深度、宽度、扇入和扇出应适当
- 深度:表示软件结构中控制的层数
- 宽度:软件结构内同一层次上的模块总数的最大值
- 扇出:一个模块直接控制(调用)的模块数目,扇出过大意味着模块过分复杂。一般一个设计的好的经典系统的平均扇出是3或4,扇出的上限是5到9
- 扇入:指有多少上级模块调用它,扇入大说明上级模块共享该模块的数目多。
- 好的软件结构顶层扇出比较高,中层扇出比较少,底层扇入到公共的使用模块中,即底层模块有高扇入
- 模块的作用域应该在控制域之内
- 作用域:指受该模块内一个判定影响的所有模块的集合
- 控制域:是这个模块本身以及所有直接或间接从属于它的模块的集合
- 力争降低模块接口的复杂程度
- 设计单入口单出口的模块
- 模块功能应该可以预测
4.4描绘软件结构的图形工具
层次图与IPO图
层次图:用方框和连线表示,连线表示上下层的调用关系
IPO图 :层次图加编号
结构图
不仅描述调用关系,还描述传递的信息和调用模式
箭头代表调用过程中传递的信息。尾部空心代表数据,实心代表控制信息
调用模块分类:简单调用、循环调用、选择调用
4.5面向数据流设计方法
面向数据流设计方法也称为结构化设计方法(SD)
数据流图分类:
- 变换流:由输入、变换中心和输出三部分组成
- 事务流:在多种事务中选择一个执行
变换分析:把具有变换流特点的数据流图映射成软件结构
五、详细设计
5.1详细设计的目的
目的:确定怎样具体地实现所要求的系统。得出对目标的精确描述
任务:
- 过程设计:即设计软件体系结构中所包含的每个模块的实现算法
- 数据设计:设计软件数据结构
- 接口设计: 设计软件内部各模块之间的接口
5.2结构程序设计
只用三种基本的控制结构就能实现任何单入口单出口的程序
三种基本控制结构:选择结构、顺序结构、循环结构
扩充的控制结构:Do-case多分枝和Do-UNTIL循环。
修正的结构程序设计:出了基本控制结构和扩展控制结构还是用BREAK结构
5.3人机界面设计
是接口设计的一个重要的组成部分
设计人机界面常遇到的4个问题:
- 系统响应时间
- 重要属性:长度和易变性
- 用户帮助设施
- 出错信息处理
- 命令交互
人机界面设计指南:
- 一般交互指南
- 信息显示指南
- 数据输入指南
5.4过程设计工具
是描述程序处理过程的工具
- 程序流程图
- 盒图(N-S图)
- PAD图
- 判定表
- 判定树
- 过程设计语言(PDL)
程序流程图:
又称为程序框图,它是历史最悠久使用广泛的描述软件设计的方法,然而它也是用的最混乱的一种方法
盒图(N-S)
处于要有一种不允许违背结构程序设计精神的图形工具的考虑
PAD图
它用二维树形结构的图来表示程序的控制流,将这种图翻译成程序代码比较容易
判定表
当算法中包含多重嵌套的条件选择时,判定表却能够清晰地表示复杂的调节组合与应做的动作之间的对应关系
组成:
- 左上部列出所有条件,左下部是所有可能的动作
- 右上部时表示各种条件组合,右下部时每种条件组合对应的动作
判定树
是判定表的变种,也能清晰地表示复杂的条件组合与应做的动作之间的对应关系
PDL:
过程设计语言也叫伪代码
5.5程序复杂度定量度量
定量的度量详细设计模块的质量
McCabe方法:将程序图转化为程序流程图再计算复杂度
计算方法:
- 流图中的区域数=环形复杂度
- 流图G的环形复杂度V(G)=E-N+2,E是流图中边的条数,N是结点数
- 流图G的环形复杂度V(G)=P+1,其中P是流图中判定结点的数目。V(G)<=10比较科学
六、实现与测试
6.1实现
软件生命周期的编码和测试统称为实现
语言选择
选择适宜的程序设计语言是减少变成的难度、减少程序测试量、容易维护的现实基础
编码风格
- 程序内部的文档
- 数据说明
- 语句构造
- 输入输出
- 效率:效率主要指处理机时间和存储器容量
6.2软件测试基础
软件测试:为了发现错误而执行程序的过程。分为编码阶段(单元测试)和测试阶段(各种综合测试)
软件测试的准则
- 所有测试都应该能追溯到用户需求
- 应该远在测试之前就指定测试计划
- Pareto原理:80%的错误是由20%的模块造成的
- 应该从“小规模”测试开始,并逐步进行大规模测试
- 穷举测试是不可能的;测试只能说明程序有错误,但不能证明程序无错误
- 为了尽最大可能的发现错误,应该由独立的第三方担任测试工作
软件测试的方法
黑盒测试法:将软件看作一个黑盒子,不考虑其内部结构和处理过程,只按照规格说明书的规定,测试软件是否能够正确接收输入数据,产生正确的输出数据。即程序是否正确的实现了其功能。又称为“功能测试”
白盒测试法:完全知道程序的内部结构和处理算法,因此可以将程序看作一个透明的百合子,根据程序内部的逻辑结构测试程序内部的主要执行通路是否能按照预定的要求正确工作。又称“结构测试”
软件测试的步骤:
- 单元测试(模块测试):将每个模块作为一个单独的实体进行测试。发现的错误编码和详细设计阶段的错误
- 子系统测试:将模块集成为一个子系统进行测试。着重测试模块的接口
- 系统测试:将子系统组装为一个完整的系统进行测试。子系统测试和系统测试总称为“集成测试”
- 验收测试(确认测试):在用户的参与下,往往使用实际的数据进行的测试。发现需求说明中的错误
- 平行运行:同时运行新开发出来的系统和将被它取代的旧系统,以便比较新旧两个系统的处理结果
6.3单元测试
测试依据:详细设计文档
测试技术(设计测试用例的方法):白盒测试技术
着重点:
- 模块接口
- 局部数据结构
- 重要的执行通路
- 出错处理通路
- 边界条件
6.4集成测试
目标:发现与接口有关的问题
实施者:独立的测试机构或第三方人员
集成方法:非渐增测试、渐增测试(自顶向下集成、自底向上集成)
自顶向下与自底向上相结合的方法:上层模块用自顶向下,下层模块用自底向上
回归测试:重新执行已经做过测试的某个子集,以保证程序的变化没有带来非预期的副作用
6.5确认测试
目标:验证软件的有效性
验证:为了确保软件正确的实现了某个特定要求而进行的一系列活动
确认:为了保证软件确实满足了用户要求而进行的一系列活动
- Alpha测试:用户在开发者的场所,在开发者指导下进行
- Beta测试: 用户在用户场所进行,遇到问题报告给开发者,让开发者进行修改
6.6白盒测试
测试用例:测试输入数据和预期的输出结果
测试方案:测试目的、测试用例的集合
- 语句覆盖:被测试程序中的每条语句至少执行一次
- 判定覆盖:使得被测程序中每个判定表达式至少获得一次”真“和”假“
- 条件覆盖:使得判定表达式中每个条件的可能的值至少出现一次
- 判定/条件覆盖:使得判定表达式中的每个条件的所有可能取值至少出现一次,并使每个判定表达式所有可能的结果也至少出现一次
- 条件组合覆盖:设计足够多的测试用例,使得每个判定表达式中条件的各种可能的值的组合都至少出现一次
- 路径覆盖:覆盖被测试程序中所有可能的路径
控制结构测试:基本路径测试、条件测试、循环测试
6.7黑盒测试
等价划分法
- 把程序的装入数据集合按输入条件划分为若干个等价类,每一个等价类相对于输入条件表示为一组有效或无效的输入
- 为每一等价类设计一个测试用例
边界值分析法
输入等价类和输出等价类的边界就是应该做中测试的程序边界情况。选取的测试数据应该刚好等于、刚好小于、刚好大于边界值
6.8调试
是在测试发现错误之后排除错误的过程
方法;蛮干法、回溯法、原因排除法
结果:找到了原因,然后改正和排除;没有找到原因,猜测一个原因,并设计附加测试用例来验证这个假设
6.9软件可靠性和可用性
软件可靠性:程序在给定时间间隔内,按照规格说明书的规定成功运行的概率
软件可用性:程序在给定的时间点,按照规格说明书的规定成功运行的概率
七、维护
7.1软件维护定义
软件维护: 是在软件已经交付使用之后,为了改正错误或满足新的需要而修改软件的过程
分类:
- 改正性维护:诊断和改正错误的过程
- 适应性维护:为了和变化了的环境是当地配合而进行的修改软件的活动
- 完善性维护:为了满足在用户提出的增加新功能或修改已有功能的要求和一般性的改进要求
- 预防性维护
7.2软件维护特点
- 结构化维护与非结构化维护差别巨大
- 非结构化维护:唯一成分是程序代码,那么维护活动从艰苦地评价代码开始
- 结构化维护:有完整的软件配置再,那么维护工作从评价设计文档开始
- 维护的代价高昂
- 维护的问题很多
7.3软件维护过程
- 维护组织
- 维护报告
- 维护的事件流
- 保存维护记录
- 评价维护活动
7.4软件可维护性
维护人员理解、改正、改动或改进这个软件的难易程度
决定软件可维护性的因素:
- 可理解性
- 可测试性
- 可修改性
- 可移植性
- 可重用性
7.5预防性维护
为了提高未来的可维护性或可靠性,主动地修改软件
7.6软件再工程过程
预防性维护也称为软件再工程
- 库存目录分析
- 文档重构
- 逆向工程
- 代码重构
- 数据重构
- 正向工程
八、面向对象方法学引论
8.1 面向对象方法学引论
按人类习惯的思维方式,以现实世界中客观存在的对象为中心来思考和认识问题
采用的思想方法与原则:抽象、集成、封装分类、聚合等
要点:
- 任何客观事物或实体都是对象。对象组成客观世界,复杂的对象可以由简单的对象组成
- 具有相同数据和操作的对象可以归并为一个类(class),对象是对象类的一个实例
- 类可以派生出子类,子类继承父类的全部特性,又可以有自己的新特新。子类与父类形成类的层次结构
- 对象之间通过消息传递相互联系
面向对象=对象+类+继承+通信
优点:
- 与人类习惯的思维方法一直
- 稳定性好
- 可重用性好
- 较易开发大型软件产品
- 可维护性好
8.2面向对象概念
略
8.3面向对象建模
模型:是一组图示符号和组织这些符号的规则,利用它们来定义和描述问题域中的属于和概念
- 对象模型:定义实体,描述系统数据,定义“对谁做”
- 动态模型:描述系统控制结构,规定“何时做”
- 功能模型:描述系统功能,指明系统应“做什么”
8.4对象模型
UML中,对象模型通常由“类图”组成
类和类之间的联系称为关系。通常分为:关联、繁华、以来和细化四种
- 关联:在类之间画一条连线
- 聚集:包括共享聚合和组合聚合
- 泛化:继承性的体现
- 依赖和细化
8.5动态模型
用来描述系统与事件相关的动态行为,从对象的“事件”和“状态”的角度出发,表现对象经过相互作用后,随时改变的不同运算顺序
动态模型包括“状态图”和“事件追踪图”
8.6功能模型
数据流图和用例图来描述功能模型
用例模型:
- 定义系统
- 寻找行为者和用例
- 描述用例
- 定义用例之间的关系
- 确认模型
8.7三种模型之间的关系
三个模型从三个侧面描述了索要开发的系统,它们相互补充、互相配合。使我们对系统的认识更全面
- 功能模型知名系统必须做什么
- 动态模型规定什么时候做
- 对象模型定义了做事情的实体
九、软件项目管理
略