第一章
软件危机
软件危机是指在计算机软件开发、 使用与维护过程中遇到的一系列严重问题和难题。 它包括两方面∶
- 如何开发软件,以满足对软件日益增长的需求;
- 如何维护数量不断增长的已有软件。
软件危机表现
- 对软件开发成本和进度的估计常常很不准确。
- 用户对已完成的软件不满意的现象时有发生。
- 软件产品的质量往往是靠不住的。
- 软件常常是不可维护的。
- 文档资料不全或不合格,必将给软件开发和维护工作带来许多难以想象的困难和难以解决的问题。
- 软件成本、软件维护费在计算机系统总成本中所占比例逐年上升。
- 开发生产率提高的速度远跟不上计算机应用普及的需求。
总结:成本、进度、质量、维护、文档
软件危机出现的原因:
- 来自软件自身的特点:
- 是逻辑部件,缺乏可见性;
- 规模庞大、复杂,修改、维护困难。
- 软件开发与维护的方法不当:
- 忽视需求分析;认为软件开发等于程序编写;
- 轻视软件维护。
- 供求矛盾将是一个永恒的主题:
- 面对日益增长的软件需求,人们显得力不从心。
消除软件危机
- 对计算机软件有一个正确的认识(软件+程序)
- 必须充分认识到软件开发不是某种个体劳动的神秘技巧,而应该是一种组织良好、理严密、各类人员协同配合、共同完成的工程项目
- 推广使用在实践中总结出来的开发软件的成功技术和方法
- 开发和使用更好的软件工具
软件工程定义
软件工程是:(1)把系统的、规范的、可度量的途径应用于软件开发、运行和维护过程,也就是把工程应用于软件;研究(1)中提到的途径。
软件工程方法学
通常把在软件生命周期全过程中使用的一整套技术方法的集合称为方法学,也称范型
软件工程方法学三要素
方法、过程、工具
- 方法,是完成软件开发任务的技术方法,回答是"怎样做"的问题。
- 工具,是为运用方法而提供的自动的或半自动的软件工程支撑环境。
- 过程,是为了获得高质量的软件所需要完成的一系列任务框架,他规定了完成各项任务的工作步骤
传统方法学、生命周期方法学、结构化范型
他们仨一个意思
结构化范型和面向对象范型的要点,及其优缺点
- 传统方法学:也称为生命周期方法学或结构化范型。
- 优点:把软件生命周期划分成基干个阶段,每个阶段的任务相对独立,而且比较简单,便于不同人员分工协作,从而降低了整个软件开发过程的困难程度。
- 缺点:当软件规模庞大时,或者对软件的需求是模糊的或会承受时间而变化的时候,开发出的软件往往不成功;而且维护起来仍然很困难。
- 面向对象方法学:
- 优点:降低了软件产品的复杂性;提高了软件的可理解性;简化了软件的开发和维护工作; 促进了软件重用。
软件生命周期
软件生命周期由软件定义、软件开发和运行维护三个时期组成,每个时期又进一步划分为若干阶段。
软件生命周期模型
软件生命周期模型是跨越整个生存期的系统开发、 运作和维护所实施的全部过程、 活动和任务的结构框架。
瀑布模型、快速原型模型、增量模型、螺旋模型、Rational统一过程(RUP)
https://blog.csdn.net/weixin_38233103/article/details/112252410
RUP的使用范围
大型的需求不断变化的复杂软件系统项目
敏捷过程适应范围
适用于商业竞争环境下对小型项目提出的有限资源和有限开发时间的约束
微软过程的适应范围
适用于商业环境下具有有限资源和有限开发时间约束的项目的软件过程模式
第二章
可行性研究
可行性研究的目的不是解决问题,而是值不值得解决问题
为什么要进行可行性研究
开发一个软件时,需要判断原定的系统模型和目标是否现实,系统完成后所能带来的效益是否大到值得投资开发这个系统的程度,如果做不到这些,那么花费在这些工程上的任何时间、人力、软硬件资源和经费,都是无谓的浪费。
可行性研究的角度.
- 经济可行性,这个系统的经济效益能超过他的开发成本么
- 技术可行性,使用现有技术能实现这个系统么
- 操作可行性,系统的操作方式在用户这个组织内能行得通么
- 必要时还要从法律、社会效益等更广泛的方面研究每种解法的可能性
可行性研究的步骤
- 复查系统规模和目标
- 研究正在使用的系统
- 导出新系统的高层逻辑模型
- 进一步定义问题
- 导出和评价供选择的解法
- 推荐行动方针
- 草拟开发计划
- 书写文档提交审查
成本估计技术
- 代码行技术
- 任务分解技术
- 自动估计成本技术
成本/效益分析时需要考虑的因素
- 货币的时间价值
- 投资回收期
- 纯收入
- 投资回收率
第三章
与用户沟通获取需求的方法
- 访谈
- 调查问卷
- 情景分析
- 面向数据流自顶向下求精
- 简易的应用规格说明技术
- 快速建立软件原型
从哪些方面验证需求的正确性
- 一致性 所有需求必须是一致的,任何一条需求不能和其他需求互相矛盾。
- 完整性 需求必须是完整的,规格说明书应该包括用户需要的每一个功能或性能。
- 现实性 指定的需求应该是用现有的硬件技术和软件技术基本上可以实现的。对硬件技术的进步可以做些预测,对软件技术的进步则很难做出预测,只能从现有技术水平出发判断需求的现实性。
- 有效性 必须证明需求是正确有效的,确实能解决用户面对的问题。
为什么要进行需求分析?
- 为了开发出真正满足用户需求的软件产品,首先必须知道用户的需求。对软件需求的深入理解是软件开发工作获得成功的前提条件,不论我们把设计和编码工作做得如何出色,不能真正满足用户需求的程序只会令用户失望,给开发者带来烦恼。
需求分析的具体任务?
- 确定对系统的综合要求
- 1、功能需求;
- 2、性能需求;
- 3、可靠性和可用性需求;
- 4、出错处理需求;
- 5、接口需求;
- 6、约束;
- 7、逆向需求;
- 8、将来可以提出的要求,分析系统的数据要求
- 分析系统的数据要求
- 导出系统的逻辑模型
- 修正系统开发计划
描述加工逻辑的工具
- 结构化语言
- 判定表
- 判定树
什么是数据流图?其作用是什么?其中的基本符号各表示什么含义?
- 数据流图:简称DFD,是SA(结构化分析)方法中用于表示系统逻辑模型的一种工具,是一种功能模型。
- 作用:它以图形的方式描绘数据在系统中流动和处理的过程,反映系统必须完成的逻辑功能.
- 基本符号有四种:
- □ 方框,表示数据的源点或终点
- → 箭头,表示数据流;
- ○ 圆或椭圆,表示加工;
- = 双杠,表示数据存储;
第四章
模块的定义
- 模块是一个词汇上邻接的程序语句序列,由边界元素限制范围,有一个聚合标识符
什么是内聚,什么是耦合
- 内聚:模块内相互作用的程度
- 耦合:模块间相互作用的程度
内聚
- 偶然内聚
- 逻辑内聚
- 时间内聚
- 过程内聚
- 通信内聚
- 功能内聚
- 信息内聚
偶然内聚
- 定义:一个模块执行多个完全不相干的操作
- 缺点:
- 可维护性退化
- 不可重用
- 解决问题:将该模块划分为不同的模块,每个模块执行一个操作
- 列子
public interface Example {
public void write();
public void eat();
public void print();
public void fly();
}
逻辑内聚
- 定义:当一个模块进行一系列相关的操作,每个操作由调用模块选择时,该模块就具有逻辑内聚
- 缺点:
- 接口难以理解(newAction(接口1, 接口2, 接口3, 接口4.........))
- 多个功能之间可能会相互纠缠,维护起来难度相当大(比如下个例子中,key1 && key2 执行打印功能,在后期维护中要改为 key2 || key5 && key6执行打印。而这个条件又和其他的功能相关联)
- 难以重用
- 解决问题:将该模块划分为不同的模块,每个模块执行一个操作
- 例子
public void example(boolean key1, boolean key2, boolean key3, ...., boolean keyn){
if (key1 && key2){
// 打印
}else if(key2 || key3 ) {
// 关机
}else if(keyn){
// 暂停
}
....
}
时间内聚
- 定义:当模块内部执行一系列与时间相关的操作时,该模块就具有时间内聚
- 缺点:
- 无法重用(一个时间顺序只能在一种场景下使用)
- 例子
public void example(){
turnOn();
loadFile();
readFile();
closeFile();
turnOff();
}
过程内聚
- 定义:当一个模块要执行一系列与产品要遵循的顺序有关的操作时,该模块就有过程内聚
- 缺点:
- 模块内部的操作之间关联弱(每个灯亮自己的,即使一个灯不亮了,也不影响其他灯亮)
- 无法重用(这个顺序只能使用于该产品)
- 例子
public void example(){
// 一个产品,如果出现故障,红绿黄灯依次亮起,
if(故障了){
turnOn("红");
turnOn("绿");
turnOn("黄");
}
}
通信内聚
- 定义:当模块要执行一系列与产品要遵循的顺序有关的操作时,并且所有操作都是在同一数据上进行,该模块就有通信内聚
- 缺点:
- 无法重用
public void example(){
Duck duck = new duck();
// 以下的颜色设置必须按照这个顺序进行
duck.setBodyColor("white");
duck.setFootColor("yellow");
duck.setEyeColor("dark");
}
功能内聚
- 定义:只执行单一操作或只完成单一目标的模块具有功能内聚
- 优点:
- 可重用
- 维护容易
信息内聚
- 定义:如果模块进行许多操作,每个都有各自的入口点,每个操作的代码相对独立,而且所有操作都在相同的数据结构上完成,则该模块具有信息内聚
// 每个操作可单独调用,即有各自的入口
// 每个操作相对独立
// 所有的操作都是在同一栈上进行的
public interface Stack {
public void initialize();
public void push();
public void pop();
public void destroy();
}
内容耦合
- 定义:一个模块直接操作或读取另一模块内的数据,则它们是内容耦合
公共耦合
- 定义:两个模块都可以存取同一全局数据
控制耦合
- 定义:一个模块向另一个模块传递控制要素,则他们是控制耦合
标记耦合
- 定义:两个模块以数据结构作为传递要素,但数据结构中的成员并未全部使用,则它们是标记耦合
数据耦合
- 定义:两个模块的所有参数是同类数据项,则他们是数据耦合(即,标记传递的参数全部被使用了)
第五章
第4代语言(4GL)的主要特征
- 友好的用户界面
- 高效的程序代码
- 应用程序生成器
在项目开发时选择程序设计语言通常考虑哪些因素?
- 项目的应用领域
- 软件开发的方法、软件执行的环境
- 算法和数据结构的复杂性以及软件开发人员的知识
第六章
集成
- 自顶向下集成
- 广度优先:a b c d e f g h i j k l m
- 优点:广度优先是一个整体的开发过程,从逻辑模块到功能模块依次向下
- 深度优先:a b e h c f i d g j l m k
- 优点:深度优先可以尽早的实现某一分支的功能,用户能尽早见到可操作的实体
- 自定向下集成的优点:
- 错误隔离
- 不必设计存根模块,只需要额外设计一个驱动模块
- 上层逻辑模块可以被多次测试,避免逻辑设计出现问题
- 缺点:底层功能模块被测试的量不够
- 广度优先:a b c d e f g h i j k l m
- 自底向上集成
第七章 测试