软件工程
采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,经济的开发出高质量的软件并维护它。
软件工程概述
软件工程概念:
采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,经济的开发出高质量的软件并维护它。
软件生命周期:

软件过程

- 阶段间具有顺序性和依赖性。
- 推迟实现的观点。
- 质量保证的观点每个阶段必须完成规定的文档;每个阶段结束前完成文档审查,及早改正错误。


增量模型优缺点:
优点:
短时间内可提交完成部分功能
逐渐增加产品功能,
用户适应产品快。
缺点:
- 增量构件划分以及集成困难。
- 容易退化为边做边改模型。


螺旋模型优缺点: .
优点:
- 利于把软件质量作为软件
开发目标。 - 减少测试
- 维护和开发不分开
缺点:
- 风险估计困难

可行性研究
可行性研究目的
用最小的代价在最小的时间内确定问题是否能够解决。(5%-10%)
可行性研究内容和目的
可行性研究步骤:
- 复查系统规模和目标。
对问题定义阶段初步确定的规模和目标进行肯定或改正并列出对目标系统的约束和限制。 - 研究目前正在使用的系统。
了解现有系统能做什么,而不花费过多时间分析怎么实现这些功能。 - 导出新系统的高层逻辑模型。
现有物理系统》现有逻辑模型》目标逻辑模型》目标物理系统 - 进一步定义问题。
分析员和用户一起再次复查系统。前四个步骤构成一个循环。 - 导出和评价供选择的解法
技术角度排除不可行方案
操作可行性排除用户不能接受方案
经济可行估算成本和收益 - 推荐行动方针。
给出是否继续的结论 - 草拟开发计划。
制定进度表
开发人员、计算机资源分析
估计每阶段成本、下阶段详细分析 - 书写文档提交审查。
数据流图
系统流程图:
是一种描绘物理系统的图,用图形符号以黑盒子形式描绘物理系统的各部
件,表达数据在系统各部件之间流动的情况。而不是对数据进行加工处理
的控制过程。
常用符号:

数据流图(DFD):
描述信息流和数据从输入到输出过程所经受的变换。没有任何具体物理部件,
只是描绘数据在软件中流动和被处理的逻辑过程。
常用符号:

数据流图画法:
- 确定系统输入输出、源点以及终点
- 画系统顶层数据流图
用加工将输入输出数据连接起来,给加工、数据等命名. - 自顶向下分解,画出分层数据流图
将加工细分,细分成几个数据流图表示.
数据字典
数据字典:
是关于数据的信息集合,即对数据流图中包含的所有元素定义的集合。
1.数据字典的内容:数据流、数据流分量(数据元素)、数据存储、处理。
2.定义数据的方法:
由数据元素组成数据的方式:顺序、选择、重复、可选

数据字典例题:
1 | 电话号码= [校内电话|校外电话] |
需求分析
需求分析的任务和阶段
需求分析任务:
- 确定对系统的综合要求
- 分析系统的数据要求
- 导出系统的逻辑模型
- 修正系统开发计划
其中综合要求有:

E-R图绘制
分析建模
模型是指为了理解事物二队十五做出的一种抽象的,对事物的一种无歧义的书面描述
模型分类:
- 数据模型: (实体-联系图) :描绘数据对象及数据对象之间的关系。
- 功能模型: ( 数据流图):描绘数据在系统中流动时被处理的逻辑过程,指明
系统具有的变换数据的功能。 - 行为模型: (状态转换图) :描绘系统的各种行为模式在不同状态间转换的方
式。
实体联系图(E-R图)
实体:描述数据对象。
属性:描述数据对象的性质。
联系:描述数据对象之间的交互方式。
- 对一联系1:1
- 对多联系1:M
- 多对多联系M:N
表示方式

实例:

状态转换图
状态:系统的行为模式,包括初态、终态、中间状态。
事件:是指在某个特定时刻发生的事情, 即对系统从一个状态转换到另一个状态的事件抽象。
表示方式
初态:实心圆
在一张状态图中只能有一个初态终态:同心圆,内为实心●
而终态可以有0至多个。状态:圆角矩形
其他图形工具
层次方框图:
表示方式:用树形结构的一系列矩形
描绘数据的层次结构。
优点:随着结构的逐步精细
对数据结构的描绘也越来越详细。

Warnier图
表示方式:用树形结构描绘
信息的层次结构。
优点:可以表明信息的逻辑组织。
可以表明某类信息出现的条件
或是否重复出现。

IPO图
表示方式:是输入、处理、
输出图的简称,能够方便地
描绘输入数据、对数据的处理
和输出数据之间的关系。
优点:简略描绘系统主要算法。

总体设计
设计过程
设计过程包括系统设计阶段和结构设计阶段:
系统设计阶段:
- 设想供选择的方案: 数据流图出发,将处理分组抛弃行不通分组。
- 选取合理的方案:上一步方案选取低、中、高成本三种方案
- 推荐最佳方案:推荐最佳方案,制定详细实现计划
结构设计阶段:
- 功能分解:对数据流图进一步细化,进行功能分解。可以
用IPO图等工具描述细化后每个处理的算法。 - 设计软件结构:层次图或结构图描绘软件结构。或数据流
图导出软件结构。 - 设计数据库
- 制定测试计划
- 书写文档
- 审查和复审
设计原理
模块化:
模块:能够单独命名,由边界元素限定的程序元素的序列,是构成程序的基
本构件。
模块化:把程序划分成独立命名且可独立访问的模块,每个模块完成一个子
功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足用户的需求。
抽象:
抽出事务的本质特性而暂时不考虑它们的细节。
逐步求精:
逐步揭露出底层细节。
Miller法则:注意力集中在(7+2)上
信息隐藏与局部化:
信息隐藏:指一个模块内包含的信息对于不需要这些信息的模块来说,是不
能访问的。主要是指模块的实现细节。
局部化:指把一些关系密切的软件元素物理地放得彼此靠近,它有助于实现
信息隐藏。
模块独立:
模块独立性:是模块化、抽象、信息隐蔽和局部化概念的直接结果。
模块独立是好设计的关键,设计是决定软件质量的关键环节。
度量标准:耦合、内聚
耦合
是对一个软件结构内不同模块之间互连程序的度量。
耦合强度取决于模块接口的复杂程度、通过接口的数据等
耦合性越高,模块独立性越弱。
耦合分类(程度从低->高):无直接耦合=》数据耦合=》标记耦合(特征耦合)=》控制耦合=》外部耦合=》公共耦合
内聚
是用来度量一个模块内部各个元素彼此结合的紧密程度的。.
内聚分类(程度从低->高):偶然内聚=》逻辑内聚=》时间内聚=》过程内聚=》通信内聚=》顺序内聚=》功能内聚
同其它模块强耦合的模块意味着弱内聚;强内聚模块意味着与其它模块间松散耦合
启发规划
- 改进软件结构提高模块独立性
- 模块规模应该适中
- 深度、宽度、扇入和扇出应适当
深度:表示软件结构中控制的层数。
宽度:软件结构内同一个层次上的模块总数的最大值。
扇出:一个模块直接控制(调用)的模块数目,扇出过大意味着模块过分复杂。
一般一个设计的好的典型系统的平均扇出是3或4,扇出的上限是5到9。
扇入:指有多少上级模块调用它,扇入大说明上级模块共享该模块的数目多。
好的软件结构顶层扇出比较高,中层扇出比较少,底层扇入到公共的实用模块中,即底层模块有高扇入。 - 模块的作用域应该在控制域之内
作用域:指受该模块内一个判定影响的所有模块的集合。
控制域:是这个模块本身以及所有直接或间接从属于它的模块的集合。 - 力争降低模块接口的复杂程度
- 设计单入口单出口的模块
- 模块功能应该可以预测
结构设计图形工具
层次图:
用方框和连线表示,连线表示上下层的调用关系

HIPQ图:
层次图加编号

结构图:
不仅描述调用关系,还描述传递的信息和调用的方式

箭头代表调用过程中传递的信息,尾部空心代表数据,实心代表控制信息

结构化设计方法(面向数据流设计方法)
交换流:由输入,变换中心和输出三部分组成

事物流:

详细设计
详细设计的任务目的
目的:
确定怎样具体的实现所要求的系统。得出对目标的精确描述
详细设计任务:
- 过程设计:即设计软件体系结构中所包含的每个模块的实现算法。
- 数据设计:设计软件数据结构。
- 接口设计:设计软件内部各模块之间的接口
结构程序设计
只使用三种基本的控制结构就能够实现任何单入口单出口的程序

扩充的控制结构:
Do-case多分支和Do-UNRTIL循环

人机界面设计
人机界面设计:是接口设计的一个重要的组成部分。
设计人机界面过程常遇到的4个问题:
- 系统响应时间
重要属性:长度和易变性 - 用户帮助设施
- 出错信息处理
- 命令交互
人机界面设计指南:
- 一般交互指南
- 信息显示指南
- 数据输入指南
过程设计工具
程序流程图:

盒图(N-S):出于要有一种不允许违背就够程序设计精神的图形工具的考虑

PAD图:它用二位树形结构的图来显示程序的控制流,将这种图翻译成车光绪代码比较容易

判定表:当算法中包含多重嵌套的条件选择时判定表却能够清晰地表示复杂的条件组合与应做的动作之间的对应关系。
组成:
左上部列出所有条件,左下部是所有可能的动作。
右上部是表示各种条件组合,右下部是和每种条件组合相对应的动作。
判定树:
是判定表的变种,也能清晰地表示复杂的条件组合与应做的动作之间的对应
关系。
PDL:过程语言也叫伪代码
程序复杂度的定量度量
程序复杂度定量度量:
定量的度量详细设计模块的质量。McCabe方法
将程序图转化为程序流程图再计算复杂度。计算方法:
流图中的区域数等于环形复杂度
流图G的环形复杂度V(G)=E-N+2, E是流图中边的条数,N是结点数。
流图G的环形复杂度V(G)=P+1,其中,P是流图中判定结点的数目。
V(G)<=10比较科学
实现和测试
软件测试基础
目标:
软件测试是为了发现错误而执行程序的过程
编码阶段(单元测试)
测试阶段(各种综合测试)
准则:
- 所有测试都应该能追溯到用户需求。
- 应该远在测试之前就制定测试计划。
- Pareto原理: 80%的错误是由20%的模块造成的。
- 应该从“小规模测试开始,并逐步进行大规模测试。
- 穷举测试是不可能的;测试只能证明程序有错误,但不能证明程序无错误。
- 为了尽最大可能的发现错误,应该由独立的第三方担任测试工作。
测试方法
黑盒测试:
将软件看作一个黑盒子, 不考虑其内部结构和处理过程,只按照规格说明书的规定,测试软件是否能够正确接收输入数据,产生正确的输出数据。即测试程序是否正确的实现了其功能。又称为“功能测试‘
白盒测试:
完全知道程序的内部结构和处理算法,因此可以将程序看作一个透明的白盒子, 根据程序内部的逻辑结构测试程序内部的主要执行通路是否能够按照预定的要求正确工作。又称“结构测试‘
测试步骤
- 单元测试(模块测试) :将每个模块作为一一个单独的实体进行测试。发现的错误编码和详细设计阶段的错误
- 子系统测试:将模块集成为一个子系统进行测试。着重测试模块的接口。
- 系统测试:将子系统组装为一个完整的系统进行测试。子系统测试和系统测试总称为”集成测试”
- 验收测试(确认测试)_ :在用户的参与下,往往使用实际数据进行的测试。发现需求说明中的错误
- 平行运行:同时运行新开发出来的系统和将被它取代的旧系统,以便比较新旧两个系统的处理结果。
单元测试
测试依据:详细设计文档
测试技术(设计测试用例的方法) :白盒测试技术
着重点:
- 模块接口
- 局部数据结构.
- 重要的执行通路
- 出错处理通路
- 边界条件
集成测试
目标:发现与接口有关的问题,
实施者:独立的测试机构或第三方人员

自顶向下与自底向上相结合的方法:
- 上层模块使用自顶向下方法
- 下层模块采用自底向上方法
回归测试:
重新执行已经做过测试的某个子集,以保证程序的变化没有带来非预期的副作用。
确认测试
又称验收测试,目标是验证软件的有效性
验证:为了保证软件正确的实现了某个特定要求二进行的一系列活动
确认:为了保证软件确实满足了用户需求二进行的一系列活动
- Alpha测试: 用户在开发者的场所,在开发者指导下进行。
- Beta测试: ,用户在用户场所进行,遇到问题报告给开发者,开发者进行修改。
白盒测试
逻辑覆盖:
测试用例:测试输入数据和预期的输出结果。
测试方案:测试目的、测试用例的集合。
- 语句覆盖:被测试程序中的每条语句至少执行一次。
- 判定覆盖:使得被测程序中每个判定表达式至少获得一次“真”值和“假”值
- 条件覆盖:使得判定表达式中每个条件的各种可能的值至少出现一次。
- 判定/条件覆盖:使得判定表达式中的每个条件的所有可能取值至少出现一次,并使每个判定表达式所有可能的结果也至少出现一次。
- 条件组合覆盖:设计足够多的测试用例,使得每个判定表达式中条件的各种可能的值的组合都至少出现一次。
- 路径覆盖:覆盖被测程序中所有可能的路径。
控制结构:
- 基本路径测试
- 条件测试
- 循环测试
黑盒测试
黑盒测试又叫功能测试。着重测试软件的功能
等价类划分法
- 把程序的输入数据集合按输入条件划分为若干个等价类,每一个等价类相对于输入条件表示为一-组有效或无效的输入。
- 为每一等价类设计一 个测试用例。
边界值分析法
输入等价类和输出等价类的边界就是应该着重测试的程序边界情况。选取的测试数据应该刚好等于、刚好小于、刚好大于边界值
调调试途径
调试(也称为纠错)是在测试发现错误之后排除错误的过程。
方法:
- 蛮干法
- 回溯法
- 原因排除法
结果:
找到了原因,然后改正和排除。
没找到原因,猜测一个原因,并设计附加测试用例来验证这个假设。
维护
软件维护定义
软件维护:
是在软件已经交付使用之后,为了改正错误或满足新的需要而修改软件的过程。
分类:
- 改正性维护:诊断和改正错误的过程(17%~21%)。
- 适应性维护:为了和变化了的环境适当地配合而进行的修改软件的活动( 18%~25%)。
- 完善性维护:为了满足在用户提出的增加新功能或修改已有功能的要求和一般性的改进要求(50~66%)。
- 预防性维护: (4%)
软件维护特点
结构化维护与非结构化维护差别巨大
非结构化维护:惟一成分是程序代码,那么维护活动从艰苦地评价程序代码开始。
结构化维护:有完整的软件配置存在,那么维护工作从评价设计文档开始。维护的代价高昂
1970年总预算的35% ~ 40%。
1980年.上升为40% ~ 60%。
1990年.上升为70% ~ 80%。维护的问题很多
理解别人写的程序通常非常困难维护的软件往往没有合格的文档,或者文档资料显著不足。
要求对软件进行维护时,不能指望由开发人员给我们仔细说明软件。
绝大多数软件在设计时没有考虑将来的修改。
软件维护不是-项吸引人的工作。
软件维护过程
- 保护组织
- 维护报告
- 维护事件流
- 保存维护记录
- 评价维护活动
软件的可维护性
维护人员理解、改正、改动或改进这个软件的难易程度。
决定软件可维护性的因素:
- 可理解性:读者理解软件的难易程度
- 可测试性:论证程序正确性的容易程度。
- 可修改性:程序容易修改的程度。
- 可移植性:把程序从: - -种计算环境(硬件配置和操作系统)转移到另一种计算环境的难易程度。
- 可重用性:同一个软件不做修改或稍加改动,就可以在不同环境中多次重复使用。
预防性维护
为了提高未来的可维护性或可靠性,而主动地修改软件。
维护一行源代码的成本可能是初始开发成本的20 - 40倍
使用现代设计概念重新设计软件结构,对未来的维护是很有帮助
软件原型已经存在,软件开发生产率将远远高于平均水平
现在用户已经有丰富的使用软件的经验,很容易确定新的需求和变更方向
利用软件再工程工具可以自动完成部分工作
在完成预防性维护的过程中,可以建立起完整的软件配置(文档、程序、数据)
软件再工程过程
预防性维护也称为软件再工程。
- 库存目录分析:分析可能成为预防性维护的对象
在今后数年内继续使用
当前正在成功使用的程序
可能最近的将来要做较大程度的修改或扩充 - 文档重构:
如果一个程序稳定,正在走向生命终点,不必为它再建立文档
只建立系统中当前正在修改的那部分的完整文档
尽量把文档工作减少到必须的最小量 - 逆向工程:
分析程序,以便在比源代码更高的抽象层次上创建出程序的某种描述的过程 - 代码重构:
重构一些编码方式难理解、测试和维护的模块代码 - 数据重构:
对数据体系结构进行修改维护 - 正向工程:
利用现代软件工程概念、原理、技术和方法,重新开发现有的某个应用系统
面对对象方法学