软件工程复习笔记
转自:Link原文链接
第一章 软件工程学概述
1.1 软件危机
软件危机是指在软件开发和维护过程中所遇到的一系列严重问题
表现:成本/进度估计不准确;闭门造车,用户不满意;不可维护;软件成本的比例逐年上升;供不应求;没有适当的文档资料。
产生软件危机的原因(理解即可 by csb)
规模加大、复杂性提高;软件是逻辑产品,缺乏“可见性”;缺乏有效的、系统的技术手段和管理方法;用户和软件开发人员的理解鸿沟(Gap);错误的认识和做法:忽视软件需求分析的重要性、认为软件开发就是写程序并设法使之运行、轻视软件测试和软件维护。
维护的费用占软件总费用的55%-70%(维护与测试比编写程序重要得多)
测试工作量占开发总工作量的40%-50%
编写程序只占开发工作量的10%-20%
软件是程序、数据及相关文档的完整集合。文档是开发、使用和维护程序所需要的图文资料。
1.2 软件工程
软件工程 是指导计算机软件开发和维护的一门工程学科,以经济地开发出高质量的软件并有效地维护它 (无论怎么解释,就是用工程化的方法开发软件 by csb)
1.2.1 软件工程的本质特性
关注大型程序的构造;中心课题是控制复杂性;软件经常变化;开发效率非常重要;和谐合作:纪律是软件开发项目的一个关键;软件必须有效地支持它的用户;一种文化背景的人替另一种文化背景的人创造产品
1.2.2 软件工程七个基本原理(读两遍即可, by csb)
用分阶段的生命周期计划严格管理;坚持进行阶段评审;实行严格的产品控制;采用现代程序设计技术;结果应能清楚地审查;开发小组的人员应该少而精;承认不断改进软件工程实践的必要性。
1.2.3 软件工程方法学
包括技术和管理两方面
软件工程三要素:工具、方法、过程
使用最广泛的方法学:面向对象方法学(将数据和行为看成是同等重要的)、传统方法学
1.3 软件生命周期(读几遍 by csb)
软件生命周期是软件产品一系列相关活动的全周期
三个大阶段(8个任务):
1.软件定义: 确定软件开发总目标;确定工程的可行性;导出实现策略及系统功能;估计资源和成本,并且制定工程进度表。
(问题定义、可行性研究、需求分析)
2.软件开发: 具体设计和实现在前一个时期定义的软件
(总体设计、详细设计、编码和单元测试、综合测试)
3.软件维护: 使软件持久地满足用户的需要
生命周期中各阶段的任务
1.问题定义: 要解决的问题是什么?
2.可行性研究: 问题是否有可行的解决办法?
3.需求分析: 目标系统必须做什么 (规格说明书)
4.总体设计(概要设计):概括地说,应该怎样实现目标系统? (确定体系结果,确定程序模由哪些模块组成、以及模块间的关系)
5.详细设计: 怎样具体地实现系统?(也成为模块设计,在这个阶段将详细地设计每个模块,确定实现模块功能所需要的算法和数据结构)
6.编码和单元测试: 编写易理解、易维护的程序; 测试编每个模块
7.综合测试: 集成测试、验收测试、现场测试或平行运行
8.软件维护: 使系统持久地满足用户的需要
1.4 软件过程
通常使用生命周期模型简介地描述软件过程。因此也成为过程模型,将生命周期划分成阶段及各阶段的执行顺序
1.4.1 瀑布模型(Waterfall model):文档驱动
特点:
1.阶段的顺序性和依赖性
2.推迟实现:区分逻辑与物理设计
3.质量保证(文档驱动)
缺点:
1.开发过程一般不能逆转
2.开发后期客户才能看到软件
文档驱动既是瀑布模型的优点也是其缺点
1.4.2 快速原型开发模型
1.4.3 增量模型
1.4.4 螺旋模型:风险驱动
1.4.5 喷泉模型
1.4.6 敏捷开发(读几遍)
1.4.7 RUP:4个阶段
开始:建立业务模型,定义项目范围
精化:系统的体系结构、项目计划、 资源需求、
构造:构件开发,软件产品
移交:软件产品移交给用户
第二章 可行性研究
2.1 可行性研究的任务(by csb)
从三方面研究:
1.技术可行性
2.经济可行性
3.操作可行性
*4.必要时还应该从法律、社会效益等广泛的方面研究每种解法的可行性
2.2 可行性研究过程(理解就行)8个
2.3 系统流程图
概括地描绘物理系统的传统工具
2.4 数据流图(DFD) 15分大题
描绘数据在软件中流动和被处理的逻辑, 不涉及具体的物理部件
2.5 数据字典
关于数据的信息的集合
●对数据流图元素(数据流、数据元素、数据存储、处理)的定义
●由数据元素组成数据的方式
(1)3种基本类型:顺序、选择、重复
(2)重复的特殊情况:可选
数据流图+数据字典=系统的逻辑模型
第三章 需求分析
需求分析的任务
1.回答“系统必须做什么?”
2.结果:软件需求规格说明书
软件需求:用户解决问题或达到目标所需要的条件或能力
需求层次:业务需求 -> 用户需求 -> 功能与非功能需求
3.1 具体任务
1.确定综合要求
功能需求、非功能需求(性能、可靠性、可用性、出错处理、接口、约束等)
2.分析数据要求
3.导出逻辑模型
4.修正开发计划
3.2 获取需求的方法
1.访谈
2.面向数据流自顶向下求精
3.简易的应用规格说明技术
4.快速建立软件原型
3.6 状态图(大题)
初态用实心圆,终点用一对同心圆(中间实心)
圆角矩形中画状态名,活动表
do/ 动作写哪里 整张图要保持一致
事件表达式:事件说明[守卫条件]/动作表达式
3.8 需求验证的四个方面
1.一致性: 需求不互相矛盾
2.完整性: 包括用户需要的每一个功能或性能
3.现实性: 现有技术可以实现
4.有效性: 确实能解决用户面对的问题
第五章 总体设计
"概括地说,系统应该如何实现?” . 2个阶段
●系统设计
划分系统:程序、文件、数据库、人工过程和文档等
●结构设计
划分程序:模块以及模块间的关系,建立软件结构
设计过程(分清是不是这9个)
①设想方案
②选取合理方案(至少3种方案:低、中、高成本)
③推荐最佳方案
————之后进入结构设计阶段————(by csb)
④功能分解
⑤设计软件结构
⑥设计数据库
⑦制定测试计划
⑧书写文档
⑨审查和复审
Q:结构设计是不是总体设计的一部分
A:yes
5.2 设计原理
1.模块化
模块不是越小越好,太小会增加接口的成本。最小成本区,曲线。
2.抽象:关注事物的本质特性,暂不考虑细节
3.逐步求精:推迟对问题细节的考虑,逐步增加细节
4.信息隐藏:内部信息(过程和数据)对外不可访问
5.局部化:把关系密切的元素放在一起
6.模块独立程度的2个定性度量标准
•内聚:模块内各元素的相关程度
•耦合:模块间的交互程度
耦合(含义)
1.内容耦合
2.共用(公共环境)耦合
3.控制耦合
4.印记(特征)耦合
5.数据耦合
原则:多用数据耦合,少用控制耦合和特征耦合,限制公用耦合,不用内容耦合,记住最好最坏!
内聚(含义)
1.偶然性内聚
2.逻辑性内聚
3.时间性内聚
4.过程性内聚
5.通信性内聚
6.顺序内聚
7.功能性内聚
8.信息性内聚
原则:力争高内聚,识别低内聚,改进以提高内聚度,记住最好最坏!
5.3 启发规则(读几遍)
1.提高模块独立性
2.模块规模适中
3.深度、宽度、扇出和扇入都应适当
4.模块的作用域应该在控制域之内
模块的作用域:受一个判定影响的所有模块集合
模块的控制域:模块及其直接或间接的从属模块集
5.降低模块接口的复杂度
6.设计单入口单出口的模块
7.模块功能可以预测
5.4 结构图(陈圣波没提)
描述软件的模块层次,反映各模块之间的调用和数据传递,不指定模块的调用顺序。
传递两种信息:数据信息(尾部空心圆)、控制信息(尾部实心圆)。
5.5 面向数据流的设计
DFD -> 结构图
两种信息流:变换流和事务流
变换流:信息以“外部世界”的形式进入,经过处理以后再以“外部世界”的形式离开。
事务流:分析每个十五以确定它的类型,并根据类型选取一条活动通路。
变换流到软件结构图的转换。
第六章 详细设计
任务
怎样具体地实现这个系统?
设计程序的“蓝图”,确定模块的处理过程
6.1结构化程序设计
结构化定理
66年被证明:任何单入口单出口的程序都可由“顺序”、“选择”和“循环”三种基本结构实现
经典定义:如果一个程序的代码块仅有顺序、选择和循环这3个基本控制结构进行连接,并且只有一个入口和出口,则称这个程序是结构化的。(五个关键! by csb)
工具(会做)
程序流程图(不易表示数据结构)
盒图 (NS图,容易表现嵌套关系,不可能任意转移控制)
PAD图(其描述的处理过程最容易转换成与之对应的高级语言程序)
判定表(互斥条件放上,动作放下)
第七章 实现 (+维护)
实现=编码+测试
7.1 编码(读几遍 by csb)
编码风格的作用就是使代码容易读;风格良好的代码更容易阅读和理解,错误更少
1.使用一致和有意义的标识符名
2.用缩进显示程序结构
3.用加括号的方式排除二义性
4.尽量不要进行浮点数的相等比较
5.避免大量使用循环嵌套和条件嵌套
6.当心运算符的副作用
7.把数定义称常量
8.利用sizeof()计算对象的大小
9.清晰的代码,而非最巧妙的代码
10.程序的注释
序言性注释和功能性注释
对一段程序注释,而不是每一个语句
11.用数据结束标记(EOF、BOF),而非让用户给出数据数目
7.2 测试(重点,好好读)
对软件规格说明、设计和编码的最后复审
测试目的:发现软件中的错误
调试:诊断并改正错误,由程序员完成
开发总工作量的40%以上
好的测试方案是极可能发现迄今尚未发现的错误(找不到错误就是不好的 by csb)
成功的测试是发现了至今尚未发现的错误的测试(没有发现错的测试是不成功的 by csb)
测试不能证明程序中没有错误
7.2.2 测试准则(读几遍 by csb)
Pareto原理:80%的错误很可能是20%的模块造成的
从“小规模”测试逐步到“大规模”测试
穷举测试不可能
应该由独立的第三方从事测试工作
7.2.3 测试方法
黑盒测试:又称功能测试或数据驱动测试
白盒测试:又称结构测试或逻辑驱动测试
7.2.4 测试步骤
●模块测试(单元测试):
主要发现编码和详细设计的错误
●子系统测试:
模块放在一起形成一个子系统来测试;着重测试模块的接口
●系统测试:
将子系统装配成一个完整的系统;主要发现软件设计中的错误,也可能发现需求说明中的错误
●验收测试(确认测试):
验证软件的有效性(是否与用户期待相符);用户参与,使用实际数据测试;主要发现系统需求说明书中的错误
●平行运行
*其中子系统测试和系统测试为集成测试
7.3 单元测试
检测最小单元—模块;主要使用白盒测试
7.3.1 测试重点
模块接口、局部数据结构、重要的执行通路、出错处理、边界条件
7.3.2 代码审查
审查小组对代码进行复审,可发现30%~70%的错误
7.3.3 计算机测试
●驱动程序
模拟被测模块的调用模块,接收测试数据,打印测试结果
●存根程序
模拟被测模块的子模块,印出入口检验或操作结果
7.4 集成测试方法(通读一遍,优缺点)
●非渐增式集成
所有模块按设计进行一次性集成
先进行单元测试,再进行集成测试
●渐增式集成
将单元测试与集成测试结合在一起
逐个将待集成的模块同已集成的那些模块结合起来进行测试
1.自顶向下集成
2.自底往上集成
3.三明治式(混合式)集成
*几种集成测试方法的优缺点
7.5 确认测试
回归测试
重新执行已经做过的测试的某个子集,以保证变化(程序改错、新模块加入等)没有带来非预期的副作用
(a) Alpha测试
在开发者的指导下,用户在开发现场进行
(b) Beta测试
用户在实际使用环境下进行测试
7.6 白盒测试技术:
7.6.1 逻辑覆盖
测试用例 = 测试数据+预期输出
以程序内部的逻辑结构为基础的设计测试用例的技术
1.语句覆盖:每个语句至少执行一次
2.判定覆盖(分支覆盖):每个判定的每个分支至少执行一次
3.条件覆盖:每个判定中的每个条件都取到可能的值
4.判定/条件覆盖:每判定中的每个条件都取到可能值,且每个判定的每个分支都至少执行一次
5.条件组合覆盖:每个判定中的各种条件组合都至少执行一次
Q:画出程序流程图,并根据流程图出数据,设计测试用例(会做)
7.7 黑盒测试技术
1.等价划分
把输入域划分成数据类,取每类中的一个典型值进行测试
设计测试用例
(1) 新增测试用例尽可能多地覆盖尚未被覆盖的有效等价类
(2) 新增测试用例覆盖一个尚未被覆盖的无效等价类
2.边界值分析
着重测试输入等价类和输出等价类的边界,选取的测试数据应该刚好等于、刚刚小于和刚刚大于边界值。
eg:若输入应为数值,则无效输入需有非数值型数据
7.8 调试(by csb)
目标:寻找软件错的原因并改正错误。
三种方法:
1.蛮干法
2.回溯法
3.原因排除法
7.9 软件可靠性
7.9.1 基本概念
软件可靠性:程序在给定的时间间隔内,按照规格说明书的规定成功地运行的概率。
软件可用性:在给定的时间点,按照规格说明书的规定,成功地运行的概率。
软件兼容性:书上没有,自己理解。(by csb)(指硬件之间、软件之间或是软硬件组合系统之间的相互协调工作的程度)
第八章 维护 (+实现)
使软件持久地满足用户的需要。
软件维护的本质是修改和压缩了的软件定义和开发过程。
占生命周期的60%以上
软件工程的一个重要目标:提高软件的可维护性,减少软件维护的代价。
四类维护
●改正性维护:诊断和改正错误的过程。17%~21%
●适应性维护:适应环境的变化而适当地修改软件。 18%~25%
●完善性维护:增加新功能或修改已有功能。 50%~66%(维护的大部分工作)
●预防性维护:改进未来的可维护性或可靠性。4%左右
8.4 可维护性
理解、改正、改进软件的难易程度
提高可维护性是支配软件工程方法学的关键目标
决定软件可维护性的因素
1)可理解性
2)可测试性
3)可修改性
4)可移植性
5)可重用性
第九、十章 面向对象
9.1 面向对象方法学概述
●1960’s:Simula-67,引入类和对象
●1980’s:面向对象分析与设计
●1980’s:面向对象方法
面向对象方法学的4个要点
1) 软件系统是由对象(Object)组成
2) 对象组成对象类(Class)
3) 类可以组成一个类层次,子类继承(inheritance)父类
4) 对象间仅能通过传递消息(Message)互相联系
OO=objects+classes+inheritance+communication with messages
面向对象 = 对象 + 类 + 继承 + 消息通信
简化了软件的开发与维护,提高了条件的可重用性
一些概念
●对象:数据结构及这些数据结构上的操作的封装体
●类:具有相同数据和相同操作的一组相似对象的集合
●消息:要求某个对象执行某个操作的规格说明
●方法:对象所能执行的操作(服务)
●属性:类中所定义的数据
●封装:对象的状态数据、代码和局部数据,外面不能直接访问
●继承:子类共享基类中定义的数据和方法的机制
●多态性:同一方法,不同的子类有不同的实现。
●函数重载:同一作用域内多个参数特征不同的函数使用相同函数名
9.3 面向对象建模
三种模型
1.对象模型:模拟客观世界实体的对象以及对象彼此间的关系的映射,描述系统的数据结构。最基本的、核心模型
2.动态模型:描述系统的控制结构。
3.功能模型:描述系统的功能
建模图形工具
类图:描述类及类与类之间的静态关系(关联、聚集、泛化等)
类的状态图:描绘对象状态及引起状态转换的事件
用例图:描述外部行为者所理解的系统功能
事件跟踪图(顺序图)
9.4 对象模型
通常使用UML提供的类图来建立对象模型
类图的关系:
1.关联(重数、
2.聚集(共享聚集、组合聚集)
3.泛化(继承)
9.5 功能模型
通常,用UML提供的状态图来描绘对象的状态、触发状态转换的时间以及对象的行为。
9.6 用例模型
用例之间的关系:
1.扩展
2.包含
3.继承(派生)
第十一章 面向对象设计
csb强调两种设计
●系统设计: 确定实现系统的策略和目标系统的高层结构
●对象设计: 确定解空间中的类、关联、接口形式及实现服务的算法
11.1 面向对象设计的准则
●模块化、抽象、信息隐藏(相似)
●耦合
(1) 交互耦合:对象之间的耦合通过消息连接来实现
减少消息中包含的参数个数,降低参数的复杂程度
减少对象发送(或接收)的消息数
(2) 继承耦合:一般化类与特殊类之间耦合
使特殊类尽量多继承并使用其一般化类的属性和服务
●内聚(csb说不用管)
(1) 服务内聚
一个服务应该完成一个且仅完成一个功能
(2) 类内聚
类的属性和服务应该全都是完成该类对象的任务所必需的
(3) 一般-特殊内聚
一般-特殊结构应该是对相应的领域知识的正确抽取
●可重用(csb强调)
从设计阶段开发
11.2 启发规则(读一读)
设计清晰易懂
一般-特殊结构深度适当:7 ± 2
设计简单的类
•1页纸大小?
•类任务明确简单
•属性和服务不要过多,简化对象间协作
使用简单的协议,消息参数少 (不要超过3个, by csb)
使用简单的服务
•3~5行源程序(动宾词描述功能)
•复杂的CASE语句 -> 一般-特殊结构代替的可能性
重用(再用或复用)
同一事物不修改或稍加改动后可重复使用
软件重用层次
知识重用。如,软件工程知识的重用。
方法和标准的重用。如,开发方法或国标。
软件成分的重用
代码重用:剪贴、包含、继承等;
设计结果重用;
分析结果重用。
类构件的重用方式
(1) 实例重用
–按需创建类实例
–用对象成员创建出更复杂的类
(2) 继承重用
–为提高继承重用的效果,关键是设计一个合理的、具有一定深度的类构件继承层次结构。
(3) 多态重用
–转换接口:重用必须重新定义的服务的集合
–扩充接口:如派生类没给出接口的新算法,则继承父类算法
extra - 题目说明
数据流图15分,用例5分,类图5分,状态图5分,顺序图5分,(白盒黑盒,NS, PAD, 判定树/表) 15分
排列性强,字比较短——填空;
用例图:小人的名字要写出来,小人用例要关联起来,用例和用例画关系图;
类图:比较简单,类已经帮你找出来了,自己负责连线(补充多重性和关系,要从题中读出来,不能瞎写);
顺序图:参与者,按照过程全部写下来,四条线,一条线一分。
状态图:比较简单。eg:借书。每个人可借多本书;借阅证的状态:可借阅和不可借阅;注意状态是圆角矩形。可借阅变为不可借阅状态:借满;不可变为可借:还书。若是信用卡:欠钱之后还能借钱(难)。