第一章 软件工程概论
1. 软件危机
- 软件危机是指:在计算机软件的开发和维护过程中所遇到的一系列严重问题。
- 软件危机包含下述两方面问题:
(1)如何开发软件,以满足对软件日益增长的需求;
(2)如何维护数量不断膨胀的已有软件。
2. 软件工程
- 软件工程是指导计算机软件开发和维护的一门工程学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程。
- 软件工程本质
关注大型程序构造
中心课题是控制复杂性
产品交付后仍然需要经常修改
开发效率非常重要
开发人员和谐合作是关键
软件有效的支持客户
一种文化背景的人为另一种文化背景的人开发
- 软件工程的基本原理
- 用分阶段的生命周期计划严格管理
- 坚持进行阶段评审
- 实行严格的产品控制
- 采用现代程序设计技术
- 结果应能清楚的审核
- 开发小组的人员应该少而精
- 承认不断改进软件工程实践的必要性
- 软件工程方法学
三要素:方法、工具、过程
主要有:传统方法学、面向对象方法学
传统方法学:
- 结构化技术
- 把软件生命周期划成若干个阶段,然后按照顺序进行
- 每个阶段开始和结束都有严格的标准
- 每个阶段结束之前都必须进行严格的审查
面向对象方法学:
- 把对象作为融合了数据及在数据上的操作行为的统一的软件结构
- 把所有对象都划分成类(类
- 按照父类与子类的关系,把若干个相关的类组成一个层次结构的系统(继承
- 对象彼此间仅能通过发送消息互相联系(封装
面向对象方法学的基本原则:尽量模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界、解决问题的方法与过程,从而使描述问题的问题空间(也称为问题域)与实现解法的解空间(也称为求解域)在结构上尽可能一致。
面向对象方法学的优点:降低了软件产品的复杂性,提高了软件的可理解性,简化了软件的开发和维护工作。面向对象方法特有的继承性和多态性,进一步提高了面向对象软件的可重用性。
3. 软件生命周期
- 三个时期、八个阶段
软件定义
问题定义:要解决的问题是什么
可行性研究:对于上一阶段所确定的问题有行得通的解法没
需求分析:为了解决这个问题,目标系统必须做什么
软件开发
系统设计
概要设计:应该怎么实现目标系统
详细设计:应该具体怎么实现这个系统
系统实现
编码和单元测试:写出正确容易理解、维护的模块,选取适当高级语言
综合测试:通过各种测试使软件达到预定要求(集成测试、验收测试、现场测试、平行运行测试等)
软件维护
运行维护:使系统持久的满足用户的需要(改正性维护、适应性维护、完善性维护、预防性维护)
4.软件过程
软件过程描述为了开发出客户需要的软件,什么人(who)、在什么时候(when)、做什么事(what)以及怎样(how)做这些事以实现某一个特定的具体目标。
通常使用生命周期模型简洁地描述软件过程,也称为过程模型。
瀑布模型
瀑布模型一直是唯一被广泛采用的生命周期模型,现在它仍然是软件工程中应用得最广泛的过程模型。
特点:
- 阶段间具有顺序性和依赖性
- 推迟实现的观点
- 质量保证的观点
优点:
- 强迫开发人员采用规范的技术方法
- 严格规定每个阶段结束之前必须交文档
- 每个阶段结束之前必须正式进行严格的技术审查和管理复审
缺点:
- 由文档驱动
快速原型模型
快速原型是快速建立起来的可以在计算机上运行的程序,它所能完成的功能往往是最终产品能完成的功能的一个子集。
快速原型模型是不带反馈环的,这正是这种过程模型的主要优点:软件产品的开发基本上是线性顺序进行的。
快速原型的本质是“快速”。开发人员应该尽可能快地建造出原型系统,以加速软件开发过程,节约软件开发成本。
线性顺序开发的主要原因:
- 原型系统已经通过与用户交互而得到验证
- 开发人员通过建立原型系统已将学会了许多东西
增量模型
增量模型也称为渐增模型。
使用增量模型开发软件时,把软件产品作为一系列的增量构件来设计、编码、集成和测试。
每个构件由多个相互作用的模块构成,并且能够完成特定的功能。使用增量模型时,第一个增量构件往往实现软件的基本需求,提供最核心的功能。
优点:
- 能在较短时间内向用户提交可完成部分工作的产品。
- 逐步增加产品功能可以使用户有较充裕的时间学习和适应新产品,从而减少一个全新的软件可能给客户组织带来的冲击。
困难:
- 在把每个新的增量构件集成到现有软件体系结构中时,必须不破坏原来已经开发出的产品。
- 必须把软件的体系结构设计得便于按这种方式进行扩充,向现有产品中加入新构件的过程必须简单、方便,也就是说,软件体系结构必须是开放的。
螺旋模型
螺旋模型的基本思想是使用原型及其他方法尽量降低风险,理解这种模型的一个简便方法是把它看作在每个阶段之前都增加了风险分析过程的快速原型的快速原型模型。适合内部的开发大型项目。
优点:
- 有利于已有软件的重用。
- 有助于把软件质量作为软件开发的一个重要目标。
- 减少了过多测试或测试不足带来的风险。
- 软件维护和软件开发过程没有本质区别。
喷泉模型
喷泉模型是典型的面向对象生命周期模型,它充分体现了面向对象软件开发过程中迭代和平滑过渡的特性。
此外还有:Rational统一过程、敏捷过程与极限编程、微软过程等,这里不再一一陈述。
第二章 结构化分析
1.可行性研究的目的
可行性研究的目的是,用最小的代价在尽可能短的时间内研究并确定客户提出的问题是否有行得通的解决办法。
通常在以下三个方面来研究每种方案的可行性:
- 技术可行性:使用现有的技术能否实现这个系统。
- 经济可行性:这个系统的经济效益能否超过它的开发成本。
- 操作可行性:这个系统的操作方式在客户组织内是否行得通。
2.可行性研究过程
典型的可行性研究过程有下述步骤:
-
复查系统规模和目标:
实质上是为了确保分析员正在解决的问题确实是要求他解决的问题。
-
研究目前正在使用的系统:
现有的系统是信息的重要来源。如果现有的系统是完美无缺的,用户自然不会提出开发新系统的要求,因此,现有的系统必然有某些缺点,新系统必须能解决旧系统中存在的问题。应该仔细阅读分析现有系统的文档资料和使用手册,也要实地考察现有的系统。常见的错误做法是花费过多时间去分析现有的系统。因为该步骤的目的是了解现有系统能做什么,而不是怎样做。
-
导出新系统的高层逻辑模型:
优秀的设计过程通常是从现有的物理系统出发,导出现有系统的逻辑模型,再参考现有系统的逻辑模型,设想目标系统的逻辑模型,最后根据目标系统的逻辑模型建造新的物理系统。
-
进一步定义问题:
可行性研究的前4个步骤实质上构成一个循环。分析员定义问题,分析这个问题,导出一个试探性的解;在此基础上再次定义问题,再一次分析这个问题,修改这个解;继续这个循环过程,直到提出的逻辑模型完全符合系统目标。
-
导出和评价供选择的解法:
分析员应该从他建议的系统逻辑模型出发,导出若干个较高层次的物理解法供比较和选择。
其次可以考虑操作方面的可行性。分析员应该根据使用部门处理事务的原则和习惯检查技术上可行的那些方案,去掉其中从操作方式或操作过程的角度看用户不能接受的方案。
接下来应该考虑经济方面的可行性。分析员应该估计余下的每个可能的系统的开发成本和运行费用,并且估计相对于现有的系统而言这个系统可以节省的开支或可以增加的收入。最后为每个在技术、操作和经济等方面都可行的系统制定实现进度表,这个进度表不需要制定得很详细,通常只需要估计生命周期每个阶段的工作量。
-
推荐行动方针
根据可行性研究结果应该决定的一个关键性问题是:**是否继续进行这项开发工程?**分析员必须清楚地表明他对这个关键性决定的建议。
如果分析员认为值得继续进行这项开发工程,那么他应该选择一种最好的解法,并且说明选择这个解决方案的理由。
通常客户主要根据经济上是否划算决定是否投资于一项开发工程,因此分析员对于所推荐的系统必须进行比较仔细的成本/效益分析。
-
草拟开发计划
分析员应该为所推荐的方案草拟一份开发计划,除了制定工程进度表之外还应该估计对各类开发人员和各种资源的需要情况,应该指明什么时候使用以及使用多长时间。此外还应该估计系统生命周期每个阶段的成本。最后应该给出下一个阶段(需求分析)的详细进度表和成本估计。
-
书写文档提交审查
应该把上述可行性研究各个步骤的工作结果写成清晰的文档,请用户、客户组织的负责人及评审组审查,以决定是否继续这项工程及是否接受分析员推荐的方案。
3.需求分析的任务
需求分析的基本任务是准确回答**”系统必须做什么?“**这个问题,需求分析的任务还不是决定系统怎样完成工作,而仅仅是确定系统必须完成哪种工作 ,也可是对目标系统提出完整、准确、清晰的和具体的要求。
为了开发出真正满足用户需求的软件产品,首先必须知道用户的需求。对软件需求的深入理解是软件开发工作获得成功的前提条件,不论人们把设计和编码工作做得如何出色,不能真正满足用户需求的程序只会令用户失望,给开发者带来烦恼。
所有分析方法都必须包括以下准则:
- 必须理解并描述问题的信息域,根据这条准则应该建立数据模型。
- 必须定义软件应该完成的功能,这条准则要求建立功能模型。
- 必须描述作为外部事物事件结果的软件行为,这条准则要求建立行为模型。
- 必须对描述信息、功能和行为的模型进行分解,用层次的方式展示细节。
要确定对系统的综合要求
-
功能需求
这方面的需求指定系统必须提供的服务。通过需求分析应该划分出系统必须完成的所有功能.
-
性能需求
性能需求指定系统必须满足的定时约束或容量约束,通常包括速度(响应时间)、信息量速率、主存容量、磁盘容量、安全性等方面的需求。
-
可靠性和可重用性需求
可靠性需求定量地指定系统的可靠性,可用性与可靠性密切相关,它量化了用户可以使用系统的程度。
-
出错处理需求
这类需求说明系统对环境错误应该怎样响应。例如,如果它接收到从另一个系统发来的违反协议格式的消息,应该做什么?
-
接口需求
接口需求描述应用系统与它的环境通信的格式。常见的接口需求有:用户接口需求;硬件接口需求;软件接口需求;通信接口需求。
-
约束
设计约束或实现约束描述在设计或实现应用系统时应遵守的限制条件。常见的约束有:精度;工具和语言约束;设计约束;应该使用的标准;应该使用的硬件平台。
-
逆向需求
逆向需求说明软件系统不应该做什么。理论上有无限多个逆向需求,人们应该仅选取能澄清真实需求且可消除可能发生的误解的那些逆向需求。
-
将来可能提出的需求
应该明确地列出那些虽然不属于当前系统开发范畴,但是据分析将来很可能会提出来的要求。这样做的目的是,在设计过程中对系统将来可能的扩充和修改预做准备,以便一旦确实需要时能比较容易地进行这种扩充和修改
4.与用户沟通方法
1. 访谈
两种基本形式:正式的和非正式的访谈。
正式访谈时,系统分析员将提出一些事先准备好的具体问题,例如,询问客户公司销售的商品种类、雇用的销售人员数目以及信息反馈时间应该多快等。
在非正式访谈中,分析员将提出一些用户可以自由回答的开放性问题,以鼓励被访问人员说出自己的想法,例如,询问用户对目前正在使用的系统有哪些不满意的地方。
当需要调查大量人员的意见时,向被调查人分发调查表是一个十分有效的做法。在访问用户的过程中使用情景分析技术往往非常有效。所谓情景分析就是对用户将来使用目标系统解决某个具体问题的方法和结果进行分析
2. 面向数据流自顶向下求精
结构化分析方法就是面向数据流自顶向下逐步求精进行需求分析的方法。通过可行性研究已经得出了目标系统的高层数据流图,需求分析的目标之一就是把数据流和数据存储定义到元素级。
数据流图是帮助复查的极好工具,从输入端开始,分析员借助数据流图、数据字典和IPO图向用户解释输入数据是怎样一步一步地转变成输出数据的。这些解释集中反映了通过前面的分析工作分析员所获得的对目标系统的认识。
3. 简易的应用规格说明技术
简易的应用规格说明技术是一种面向团队的需求收集技术。
该技术提倡用户与开发者密切合作,共同标识问题,提出解决方案要素,商讨不同方案并指定基本需求。
4. 快速建立软件原型
快速建立软件原型是最准确、最有效、最强大的需求分析技术。所谓软件原型,就是快速建立起来的旨在演示目标系统主要功能的可运行程序。构建软件原型的要点是,它应该实现用户看得见的功能,省略目标系统的”隐含“功能。
软件原型应该具有的第一个特性是”快速“,第二个特性是”容易修改“。
5.分析建模与规格说明
6. 系统流程图 — 实体联系图 — 数据流图 — 数据字典 — 状态转换图
看例题和课后题掌握
系统流程图
系统流程图表的的是数据在系统各部件之间流动的情况,而不是对数据加工处理的控制过程,因此系统流程图是物理数据流图而不是程序流程图。
数据流图
数据流图(DFD)是一种图形化技术,它描绘信息流和数据从输入移动到输出的过程中所经受的变换。在数据流图中没有任何具体的物理部件,它只是描绘数据在软件中流动和被处理的逻辑过程。数据流图是系统逻辑功能的图形表示,即使不是专业的计算机技术人员也容易理解它,因此是分析员与用户之间极好的通信工具。
数据字典
数据字典是关于数据的信息的集合,也就是对数据流图中包含的所有元素的定义的集合。数据字典的作用是在软件分析和设计的过程中给人提供关于数据的描述信息。
数据字典一般由下列4类元素定义:
- 数据流
- 数据流分量(即数据元素)
- 数据存储
- 处理
数据元素组成数据的方式:
- 顺序 即以确定次序连接两个分量
- 选择 即从两个或多个可能的元素中选取一个
- 重复 即把指定的分量重复零次或多次
- 可选 即一个分量是可有可无的(重复零次或一次)
7.成本/效益估计
1.成本估计
软件开发成本主要表现为人力消耗(乘以平均工资则得到开发费用)。成本估计不是精确的科学,因此应该使用几种不同的估计技术以便相互校验。
- 代码行技术
比较简单的定量估算方法,估计出源代码行数以后,用每行代码的平均成本乘以行数就可确定软件的成本。每行代码的平均成本取决于软件的复杂程度和工资水平,
- 任务分解技术
首先把软件开发工程分解为若干个相对独立的任务,再分别估计每个单独任务的成本,最后累加得出总成本。
- 自动估计成本技术
采用自动估计成本的软件工具,减轻人的劳动,估计结果更客观。
2.成本/效益分析方法
主要从以下四个方面考虑;
- 货币的时间价值
- 投资回收期
- 纯收入
- 投资回收绿率
8.验证软件需求
从以下4个方面
- 一致性:所有需求必须一致,任何一条需求不能和其他需求冲突
- 完整性:需求必须是完整的,规格说明书应包括用户需要的每一个功能或性能
- 现实性:在现有的硬件技术和软件技术上可以实现
- 有效性:必须证明需求是正确有效的
第三章 总体设计
总体设计的基本目的就是回答“概括地说,系统应该如何实现”这个问题,因此,总体设计又称为概要设计或初步设计。
总体设计阶段的另一项重要任务是设计软件的结构,也就是要确定系统中每个程序是由哪些模块组成的,以及这些模块相互间的关系。
结构化设计技术的基本要点如下:
- 软件系统是由层次化结构的模块构成的
- 模块是单入口和单出口的
- 构造和联结模块的基本准则是模块独立
- 用图来描述软件的系统结构,并且使软件结构与问题结构尽量一致
概要设计
概要设计也称总体设计或初步设计,这个设计阶段主要完成下列两项任务。
方案设计
首先设想实现目标系统的各种可能解决方案。然后根据系统规模和目标,综合考虑技术、经济、操作等各种因素,从设想出的供选择方案中选出若干个合理的方案。最后,综合分析,选出最佳方案,并制定详细实现计划。
软件体系结构设计
确定每个程序是由那些模块所组成,以及这些模块相互间的关系。还应该进一步改变软件结构,以便获得更好的体系结构。
详细设计
详细设计阶段主要完成以下三项任务:
- 过程设计,即设计软件体系结构中所包含的每个模块的实现算法
- 数据设计,即设计软件中所需要的数据元素
- 接口设计,即设计软件内部各个模块之间、软件与协作系统之间以及软件与使用它的人之间的通信方式
1.设计过程
总体设计过程通常有两个主要阶段组成:系统设计阶段,确定系统的具体实现方案;结构化设计阶段,确定软件结构。
典型的总体设计过程包括下述9个步骤:
-
设想供选择的方案
需求分析阶段得出的数据流图是总体设计的极好的出发点。
-
选取合理的方案
通常至少选取低成本、中等成本和高成本的3种方案
对每个方案都应准备以下四份资料:
1)系统流程图
2)组成系统的物理元素清单
3)成本/效益分析
4)实现这个系统的进度计划
-
推荐最佳方案
-
功能分解
对程序(特别是复杂的大型程序)的设计,通常分为两个阶段完成:首先进行结构设计,然后进行过程设计。
为确定软件结构,首先需要从实现角度把复杂的功能进一步分解。分析员结合算法描述仔细分析数据流图中的每个处理,如果一个处理的功能过分复杂,必须把它的功能适当地分解成一系列比较简单的功能。
-
设计软件结构
通常程序中的一个模块完成一个适当的子功能。应该把模块组织成良好的层次系统,顶层模块调用它的下层模块以实现程序的完整功能,每个下层模块再调用更下层的模块,完成程序的一个子功能,最下层的模块完成最具体的功能。
-
设计数据库
-
制定测试计划(主要是功能测试问题)
在软件开发的早期阶段考虑测试问题,能促使软件设计人员在设计时注意提高软件的可测试性。
-
书写文档
文档通常有下述几种:
(1)系统说明
(2)用户手册
(3)测试计划
(4)详细的实现计划
(5)数据库设计结果
-
审查与复审
最后应该对总体设计的结果进行严格的技术审查,在技术审查通过之后再由客户从管理角度进行复审。
2.设计原理
1.模块化
模块是由边界元素限定的相邻程序的序列,而且具有一个总体标识符代表它。
模块化就是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集合起来构成一个整体,可以完成指定的功能满足用户的需求。
模块化是为了使一个复杂的大型程序能够被人的智力所管理,是软件应该具有的唯一属性。
每个程序都相应地有一个最适当的模块数M,使得系统开发成本最小。
2.抽象
人们在认识复杂现象的过程中使用的最强有力的思维工具就是抽象。
现实世界中一定事物、状态或过程之间总存在着某些相似的方面(共性)。把这些相似的方面集中概括起来,暂时忽略它们之间的差异,这就是抽象。
或者说,抽象就是抽出事物的本质特性而暂时不考虑其他细节。
逐步求精和模块化概念,与抽象是密切相关的。
3.逐步求精
为了能集中精力解决主要问题而尽量推迟对问题细节的考虑。
求精实际上是细化过程,抽象与求精是一对互补的概念。
4.信息隐藏和局部化
应该这样设计和确定一个模块,使得一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是不能访问的。
局部化的概念和信息隐藏概念是密切的相关的。所谓局部化是指把一些关系密切的软件元素物理地放的彼此靠近。
5.模块独立
模块独立的概念是模块化、抽象、信息隐藏和局部化概念的直接结果。
模块的独立性很重要。主要有两个理由:
- 有效的模块化的软件比较容易开发出来
- 独立的模块比较容易测试和维护。
模块的独立程度可以由两个定性标准度量,这两个标准分别称为内聚和耦合。
-
耦合
耦合是对一个软件结构内不同模块之间互连程度的度量。
如果两个模块中的每一个都能独立地工作而不需要另一个模块的存在,那么它们彼此完全独立,这意味着模块之间无任何连接,耦合程度最低。
四种耦合:
-
数据耦合
如果两个模块彼此间通过参数交换信息,而且交换的信息仅仅是数据,那么这种耦合称为数据耦合。
数据耦合是低耦合,系统中至少存在这种耦合。
-
控制耦合
如果传递的信息中有控制信息,则这种耦合称为控制耦合。
控制耦合是中等程度的耦合,它增加了系统的复杂程度。控制耦合往往是多余的,在把模块适当分解之后通常可用数据耦合代替它。
-
特征耦合
把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素时,就出现了特征耦合。
-
公共环境耦合
当两个或多个模块通过一个公共数据环境相互作用时,它们之间的耦合称为公共环境耦合。
公共环境可以是全程变量、共享的通信区、内存的公共覆盖区、任何存储介质上的文件、物理设备等。
公共环境耦合的复杂程度随耦合的模块个数而变化,当耦合的模块个数增加时复杂程度明显增加。如果只有两个模块有公共环境,那么这种耦合有下面两种情况:
(1)一个模块往公共环境送数据,另一个从公共环境中获取数据。是比较松散的耦合。
(2)两个模块都既往公共环境送又取,这种耦合比较紧密,介于数据耦合和控制耦合之间。
如果两个模块的共享数据很多,这时可以用公共环境耦合。
-
内容耦合
耦合程度最高。如果出现下列情况之一,两个模块之间就发生了内容耦合:
(1)一个模块访问另一个模块的数据、
(2)一个模块不通过正常入口而转到另一个模块内部
(3)两个模块有一部分程序代码重叠
(4)一个模块有多个入口
应坚决避免使用内容耦合!
应该采取下述设计原则:
- 尽量使用数据耦合
- 少用控制耦合和特征耦合
- 限制公共环境耦合的范围
- 完全不使用内容耦合
-
-
内聚
内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展。简单说说,理想内聚的模块只做一件事情。
内聚和耦合是密切相关的,模块内的高内聚往往意味着模块间的松耦合。
-
低内聚
(1)偶然内聚:一个模块完成一组任务,这些任务间彼此之间即使有联系,关系也很松散。
(2)逻辑内聚:一个模块完成的任务在逻辑上属于相同或者相似的一类。
(3)时间内聚:一个模块中包含的任务必须在同一段时间内执行。
-
中内聚
(1)过程内聚:一个模块中的处理元素是相关的,而且必须以特定的次序执行。
(2)通信内聚:模块中所有元素使用同一个输入数据或产生同一个输出数据。
-
高内聚
(1)顺序内聚:一个模块内的处理元素和同一个功能密切相关,而且这些处理必须顺序执行(一个处理元素的输出数据作为下一个元素的输入数据)。
(2)功能内聚:模块内所有处理数据属于一个整体,完成一个单一内容。功能内聚是最高程度的内聚
-
设计时力争做到高内聚,并且能够辨认出低内聚的模块,有能力通过修改设计提高模块的内聚程度并且降低模块间的耦合程度,从而获得较高的模块独立性。
3.启发规则
- 改进软件结构提高模块独立性
- 模块规模应该适中
- 深度、宽度、扇出和扇入都应适当
- 模块的作用域应当在控制域之内
- 力争降低模块接口的复杂程度
- 设计单入口单出口的模块
- 模块功能应该可以预测
4.描绘软件结构的图形工具
1.层次图和HIPO图
2.结构图
5.面向数据流的设计方法
1.数据流类型
- 变换流:信息以”外部世界“形式进入系统,经过加工处理后以再以”外部世界“的形式离开系统。
- 事物流:这种数据流”以事物为中心“,事务中心完成以下任务:(1)接受输入数据(输入数据又称事务)(2)分析每个事务以确定它的类型(2)根据事务类型选取一条活动通路
2.设计步骤
面向数据流方法主要有下述几个步骤:
- 复查基本系统模型
- 复查并精化数据流图
- 确定数据流图具有变换特性还是事物特性
- 确定数据流边界
- 完成“第一级分解”
- 完成”第二级分解“
- 优化
2019/6/1 21:51 先整理到这里