3.1 构化需求分析
需求分析:指开发人员要准确理解用户的要求,进行细致的调查分析,将用户非形式的需求陈述化为完整的需求定义,再由需求定义转换到相应的形式功能规约(需求规格说明)的过程。
需求分析所处于软件开发过程的开始阶段,但它对于整个软件开发过程以及软件产品质量是至关重要的。
在进行软件系统/产品的需求工作中,通常面临三大挑战:
4. 问题空间理解;
5. 人与人之间的通信;
6. 需求的变化性。
应对三大挑战的软件开发方法:结构化方法、面向数据结构方法、面向对象方法等。
抽象和分解是结构化分析方法采用的两个基本手段:
需求阶段的主要任务:需求发现、需求分析和需求验证,最终形成系统的软件需求规格说明书。
3.1.1 基本术语
- 数据流
在结构化分析方法中,数据流是数据的流动。
例图: - 加工
加工是数据的变换单元,即它接受输入的数据,对其进行处理,并产生输出;在使用中,一般给出标识,且标识为动宾结构。
例图:
- 数据存储
在结构化分析方法中国,数据存储是数据的静态结构。
例图:
- 数据源和数据潭
数据源是数据流的起点;数据潭是数据流的归宿地。
数据流和数据潭是系统之外的实体,可以是人、物或者其它软件系统。
例图:
3.1.2 系统功能模型表示
需求分析的首要任务是建立系统功能模型。
结构化分析方法给出一种能表达功能模型的工具,即数据流图,简称DFD图。
软件工程分析工具:
名称 | 描述 |
---|---|
HIPO | 总体设计的工具 |
N-S图 | 详细设计工具 |
PAD图 | 详细设计的工具 |
DFD图 | 结构化分析方法的表达功能模型的工具 |
3.1.3 建模过程
自顶向下,功能分解
- 建立系统环境图,确定系统语境
结构化方法通过系统顶层数据流图来定义系统语境。
一个飞机票预定系统的顶层数据流图/系统环境图
Tips:
数据源和数据潭以及与之相关的数据流较易确定。
对于最顶层的“大加工”,其标识一般采用待建系统名字。
- 自顶向下,逐步求精,建立系统层次数据流图
Tips:
这些图互为“父子”关系;
从0层开始就对其中的“加工”进行编号:子图号.加工顺序号。
由“父图”生产“子图”的步骤:
在各加工之间建立合理的关联,必要时引入数据存储,使之形成一个有机的整体。
- 定义数据字典
目标:定义数据流图包含的所有数据流和数据存储的数据结构,直到给出构成以上数据的各数据项的基本数据类型。
数据的基本结构分为:顺序结构、选择结构和重复结构。
顺序结构:数据A由数据B和数据C顺序构成的,并记为“+”。
例:学生成绩=姓名+性别+学号+科目+成绩
选择结构:数据A是由数据B或者由数据C定义的,即数据不可能同时是B或C,并记为“|”。
例:性别=男|女
重复结构:数据A是由多个重复的数据B构成的,并记为“{ }”。
例:学生成绩表={学生成绩}
符号 | 描述 |
---|---|
= | 定义为 |
+ | 顺序 |
或 | 选择 |
{} | 重复 |
m…n | 子界 |
在数据字典中,三种条目:
- 描述加工
目的:依据系统的数据流图,给出其中每一个加工的小说明,对DFD图中的每一加工只需要给出加工的输入数据和输出数据之间的关系,即从外部来“视察”一个加工的逻辑。
有3种表达工具:
(1)、结构化自然语言
适用于输入数据和输出数据之间的逻辑关系比较简单的情况。
结构化自然语言的语法由内、外两层。
外层语法描述操作的控制接结构:如顺序、选择、循环等;
内层语法没有什么限制,一般使用自然语言描述。
特点:
- 没有形式语言那样严格;
- 简单易懂,又避免了自然语言结构松散的缺点。
结构化自然语言是介于形式语言和自然语言之间的一种语言。
(2)、判定表
适用于输入数据和输出数据之间的逻辑关系比较复杂的情况。
通常用于不易用自然语言表达清楚或需要大篇幅才能表达清楚的加工。
适用于当描述的加工由一组操作组成,且是否执行某些操作或操作的执行情况取决与一组条件时。
‘I’区内列出所有的条件类别;
‘II‘区内列出所有的条件组合;
’III’区内列出所有的操作;
’IV‘区内列出在相应的组合条件下,某个操作是否执行或执行情况。
(3)、判定树
适用于输入数据和输出数据之间的逻辑关系比较复杂的情况。
3.2 结构化设计
结构化设计的主要任务:在需求分析的基础上,定义满足需求所需要的结构,即针对给定的问题,给出该问题的软件解决方案,确定怎么做的问题。
为控制软件设计的复杂性,结构化设计进一步分为总体设计和详细设计。
总体设计将系统分解成一个个“黑盒子”,详细设计描述其细节。
3.2.1 总体设计
- ** 总体设计的目标及其表示**
结构化方法在总体设计中引入了两个基本概念:
- 模块,即指软件中具有特定标识的独立成分;是执行一个特殊任务的一个过程以及相关的数据结构。
- 模块调用:模块之间的一种使用关系。
基本任务:把系统的功能需求分配到一个特定的软件体系结构中,建立系统的模块结构,只声明其作用或功能。
表达这一软件体系结构的工具主要有以下几种:模块结构图、层级图(H图)和HIPO图(H图+IPO图)。
(1)、Yourdon提出的模块结构图
结构图是一种描述软件宏观结构的图形化工具。较高层级:控制(或管理)模块;较低层级:从属模块。
(2)、HIPO图(层级图 + 输入/处理/输出)
- 总体设计步骤
待建系统的DFD图可以分为:变换型数据流图和事务型数据流图。
(1)、变换型数据流图
具有较明显的输入部分和变换(或称主加工)部分之间的界面】变换部分和输出部分之间界面的DFD图。
(2)、事务型数据流图
数据到达一个教工T,该加工T根据输入数据的值,在其后的若干动作序列(或称一个事务)中选出一个来执行。
处理T称为事务中心,完成以下任务:
- 接收输入数据;
- 分析并确定对应的事务;
- 选取与该事务对应的一条活动路径。
事务型数据流图所描述系统的数据处理模式为集中——发散式。
结构化设计方法基于自顶向下,功能分解的基本原则,针对两种不同类型的数据流图,分别提出变换设计和事务设计。
变换设计 目标:将变换型数据流图映射为模块结构图。
事务设计 目标:将事务型数据流图映射为模块结构图。
总体设计分为3阶段:
- 第一阶段:初始设计(将给定的数据流图转换为模块结构图)
- 第二阶段:精化设计(高内聚低耦合,精化模块结构图,设计数据结构和接口)
- 第三阶段:复审阶段(对高层软件结构进行复审,精化)
变换设计与事务设计的基本步骤:
变换设计 | 事务设计 |
---|---|
设计准备——复审并精化系统模型 | 设计准备——复审并精化系统模型 |
确定输入、变换、输出这三部分之间的边界 | 确定事务处理中心 |
第一级分解——系统模块结构图顶层和第一层的设计 | 第一级分解——系统模块结构图顶层和第一层的设计 |
第二级分解——自顶向下,逐步求精 | 第二级分解——自顶向下,逐步求精 |
变换设计与事务设计的区别及联系,分别从两者的目的、组成、任务来看。
●变换设计:
将变换型数据流图映射为模块结构图;
组成:获取数据变换数据(核心)和输出数据;
设计一个主控模块来协调和控制其它模块,比较机械。
●事务设计:
将事务型数据流图映射为模块结构图;
事务中心需完成3个任务:接收数据、分析并确定事务和选取活动路径。
联系:以变换设计为主,事务设计为辅。
实践中,一个大型的软件系统一般是变换型流图和事务型流图的混合结构。
●在软件总体设计中,通常以变换设计为主,事务设计为辅,进行结构设计;
●先利用变换设计,把软件系统分为输入、中心变换和输出3个部分,设计上层模块;
●再根据各部分DFD图的结构特点,适当地利用变换设计和事务设计进行细化,得到初始模块结构图;
●最后按高内聚低耦合的原则,对初始的模块结构图进行精化,得到最终模块结构图。
- 模块化及启发式规则
实现精化设计的目的是:基于模块”高耦合低内聚“的原则,提高模块的独立性。
(1)、模块化
模块是执行一个特殊任务的一个过程以及相关的数据结构。
【模块 = 接口 + 模块体】
模块化涉及的两个问题:
- 如何将系统分解成软件模块:“分而治之”和“抽象”。
- 如何设计模块:伪码、问题分析图PAD、N-S图(盒图)。
模块化是把一个待开发的软件分解成若干简单的、具有高内聚低耦合的模块的过程。
结构化软件设计是一种典型的模块化方法,而模块化是系统设计基本原理/原则之一。
1)、耦合:不同模块之间互相依赖的度量。
内容耦合:一个模块直接修改或操作另一个模块的数据。耦合程度最高,尽量避免使用。
公共耦合:两个或两个以上的模块共同引用一个全局数据项。
控制耦合:一个模块通过接口向另一个模块传递一个控制信号(如开关量、标志),接收信号的模块根据信号值进行适当的动作。
标记耦合: 模块A通过接口向两个模块B和C传递一个公共参数,称模块B和C间存在一个标记耦合。
数据耦合:模块之间通过参数来传递数据。耦合程度最低,存在普遍
耦合度从高到低的顺序:内容耦合、公共耦合、控制耦合、标记耦合、数据耦合。
设计原则:
- 尽量使用数据耦合
- 少用控制耦合
- 限制公共耦合的范围
- 尽量避免使用内容耦合
2)、内聚:一个模块内部各成分之间相互关联的度量。
高内聚:一个模块中各部分之间存在着很强的依赖。
低内聚:一个模块中各部分之间存在着较少的依赖。
偶然内聚:一个模块的各成分之间基本不存在任何关系。
逻辑内聚:几个逻辑上相关的功能被放在同一模块中。
时间内聚:一个模块完成的功能必须同一时间内执行。
过程内聚:处理必须以特定的次序执行。
通信内聚:所有成分都操作/生成同一数据集。
顺序内聚:各个成分和同一个功能密切相关,而且一个成分的输出作为另一个成分的输入。
功能内聚:模块的所有成分对于完成功能都是基本的。
衡量模块独立性的指标:耦合和内聚;
模块化的目标:基于模块“高耦合低内聚”的原则,提高模块独立性。
(2)、启发式规则
实现高内聚低耦合的启发式规则:
- 改进软件结构,提高模块独立性;
- 力求模块规模适中;
- 力求深度、宽度、扇出和扇入适中;
- 尽力使模块的作用域在其控制域之内;
- 尽力降低模块接口的复杂度;
- 力求模块功能可以预测。
深度:控制的层数,粗略标志一个系统的规模和复杂程度。
宽度:同一个层次上魔魁啊总数的最大值。
扇入:表明有多少个上级模块直接调用它。
扇出:一个模块直接调用的下级模块数目。
设计的很好的软件结构:
- 顶层模块:扇出较大;
- 中间层模块:扇出较小;
- 底层模块:扇入较大;
注意:模块的扇入大,即共享该模块的上级模块数目越多,可提高软件的服用性。
** 控制域**:模块本身以及所有直接或间接从属它的模块集合。
作用域:受该模块内一个判定所影响的所有模块的集合。
3.2.2 详细设计
- 结构化程序设计
结构化程序设计方法是一种基于结构的编程方法,采用顺序结构、选择结构以及重复结构进行编程,每一结构只允许一个入口和一个出口。
Tips:
实际上,用顺序结构和循环结构完全可以实现选择结构;理论上最基本的控制结构只有两种:顺序结构、循环结构。
- 详细设计工具
(1)、程序流程图(程序框图)
优点:对控制流程的描绘很直观,便于初学者掌握。
缺点:不是一种逐步求精的工具、影响甚至破坏好的系统结构设计、不宜表示数据结构。
使用的主要符号:顺序结构、选择结构、循环结构。
(2)、N-S图(盒图)
支持“自顶向下逐步求精”
a) 顺序 、b)IF-THEN-ELSE型、c)CASE型、d)循环、e)调用子程序P
(3)、PAD图(问题分析图)二维树形结构图;自上而下、从左向右
(4)、类程序设计语言(PDL或伪码)
“混合”语言
借用某种结构化程序设计语言的关键子作为语法框架;
使用某种自然语言的词汇。
课后习题
一、 解释以下术语:
-
需求分析:分析是系统地使用信息,对一个问题的估算。软件需求分析是这一概念的特化,即系统化地使用“数据流”、“加工”、“数据存储”、“数据源”和“数据潭” 等术语所表达的信息,对待建系统“是什么”给出一个估算——系统概念模型。
-
软件设计:在需求分析的基础上,定义满足需求所需要的结构,即针对给定的问题,给出该问题的软件解决方案,确定“怎么做”的问题。
-
数据流图:表达功能模型的工具,即数据流图(Dataflow Diagram)简称DFD图,简单的说,DFD图是一种描述数据变换的图形化工具,其中饮食的元素可以是数据流、数据存储、加工、数据源和数据潭等。
-
变换型数据流图:具有较明显的输入部分和变换(主加工)部分之间的界面变换部分和输出部分之间界面的数据流图。
-
事务型数据流图:数据到达一个加工T,该加工T根据输入数据的值,在其后的基干动作序号(称为一个事务)中选出一个来执行。
-
模块:执行一个特殊任务的一个过程以及相关的数据结构
-
何谓模块耦合?简述模块耦合的类型。
答:不同模块之间互相依赖的度量。
内容耦合:一个模块直接修改或操作另一个模块的数据。耦合程度最高,尽量避免使用。
公共耦合:两个或两个以上的模块共同引用一个全局数据项。
控制耦合:一个模块通过接口向另一个模块传递一个控制信号(如开关量、标志),接收信号的模块根据信号值进行适当的动作。
标记耦合: 模块A通过接口向两个模块B和C传递一个公共参数,称模块B和C间存在一个标记耦合。
数据耦合:模块之间通过参数来传递数据。耦合程度最低,存在普遍
- 何谓模块内聚?简述模块内聚的类型。
答:指一个模块内部各成分之间相互关联的度量。
偶然内聚:一个模块的各成分之间基本不存在任何关系。
逻辑内聚:几个逻辑上相关的功能被放在同一模块中。
时间内聚:一个模块完成的功能必须同一时间内执行。
过程内聚:处理必须以特定的次序执行。
通信内聚:所有成分都操作/生成同一数据集。
顺序内聚:各个成分和同一个功能密切相关,而且一个成分的输出作为另一个成分的输入。
功能内聚:模块的所有成分对于完成功能都是基本的。
- 何谓模块的控制域和模块的作用域?并举例说明
** 控制域**:模块本身以及所有直接或间接从属它的模块集合。
作用域:受该模块内一个判定所影响的所有模块集合。