目录
结构化方法是一种系统化开发软件的方法,该方法基于模块化的思想,包括结构化分析、结构化设计和结构化编程 ,本文重点介绍结构化分析和结构化设计
本文参考教材:沈备军老师的《软件工程原理》大多图片来源其中
结构化分析
结构化分析是一种以组织和规范化系统设计的方式。结构化方法有助于将复杂的软件系统分解为更简单、易于理解的部分,从而方便开发和维护
组成结构如下所示,核心的数据字典(DD),从DD出发可构成三种图
DFD(数据流图)
数据流图是一种图形工具,用于表示系统中数据的流动以及各个处理数据的模块。它是结构化分析方法的一部分,强调数据的流动和数据处理的过程。
ERD(实体关系图)
ER图是一种用于描述系统中的实体以及它们之间关系的图形工具。实体表示系统中可以区分的对象,而关系表示这些对象之间的联系。
STD(状态图)
状态变迁图是一种描述系统中对象状态及其状态之间转换关系的图形工具。它适用于建模有限状态机(Finite State Machine)。
数据流图DFD
数据流图(DFD)使用4种基本图形符号进行建模:
圆边矩形或者圆形代表加工;
箭头代表数据的流向,数据名称总是标在箭头的边上;
方框表示数据的源(发送数据)和宿(接收数据),即与系统打交道的人或外界系统
双杠(或单杠)表示数据存储(具体实现有文件系统、数据库系统,存储介质:磁盘、磁带或其它存储介质)
分层数据流图:自顶向下逐层分解+按照层次结构绘制+每张图中的加工个数大致控制在"7+-2"范围内
顶层图:描述了软件系统与外界之间的数据流,只有一张图,一个加工(代表整个软件系统)
0层图:顶层图中加工经过分解后的图,也只有一张
中间层:除了顶层、0层、底层的其它图
底层图:处于最底层的图,底层图中所有的加工不能再分解
父图和子图:如果某图A中某一个加工分解成一张子图B,则称A是B的父图,B是A的子图,若父图中有n个加工,则它可以有0-n张子图
加工编号:顶层图只有1个加工,不必编号,0层图的加工编号分别为1、2、3...子图号就是父图中被分解的加工号,如果父图中加工号为x的加工分解为某一子图,则该子图中加工编号分别为x.1,x.2,x.3......
画分层数据流图就是先构建顶层DFD,然后对顶层DFD图细化,构建0层DFD,接着继续细化
下面以考务处理系统为例,来展示上面的概念:
这是顶层DFD,可以发现只有一个加工,加工的名称就是系统的名称
分解成0层图如下:
可以看到这样以来,就出现了两个加工,下面对0层图中加工序列为2的加工进行分解,分解成1层图(这知识其中一个1层图,上面已经说了如果有n个加工是可以有0-n个子图的)
通过上面可以发现几个规律:
1.任何一张DFD的子图边界上的输入/输出数据流必须与其父图中对应加工的输入/输出数据流保持一致
比如上面顶层图加工输出流6个,输入流3个,分解成0图,边界上的输入/输出流也是这个数量
2.每个加工至少有一个输入数据流和一个输出数据流
3.在整套分层数据流图中,每个数据存储应该至少有一个加工对其进行读操作,另一个加工对其进行写操作,但对于一张DFD来说,可以只写或只读不写
定义数据字典
数据字典是描述数据的信息的集合,是对 系统中使用的所有数据元素或者数据流图中包含的所有元素 的定义的集合。是为了描述在结构化分析过程中定义对象的内容时,使用的一种半形式化的工具。
数据字典的信息包括:
数据的名称、别名、简要简述,数据流组成、数据流来源、数据流去向、数据类型、取值范围、峰值等信息
其中对于"数据流组成"这个板块可以用下面的符号表述:
还是以上面考务处理系统为例,定义"成绩清单"的字典条目如下:
实体关系图(E-R图)
实体-关系图(Entity-Relationship Diagram,简称E-R图)是一种用来表示实体及其之间关系的图形化工具,包含以下元素:
矩形框:表示实体,在框中记入实体名。
菱形框:表示联系,在框中记入联系名。
椭圆形框:表示实体或联系的属性,将属性名记入框中。对于主属性名,则在其名称下划一下划线。
连线:实体与属性之间;实体与联系之间;联系与属性之间用直线相连,并在直线上标注联系的类型。(对于一对一联系,要在两个实体连线方向各写1; 对于一对多联系,要在一的一方写1,多的一方写N;对于多对多关系,则要在两个实体连线方向各写N,M。)
结构化设计
结构化设计的任务就是把用DFD表示的分析模型转换为以结构图(Structure Chart,SC)表示的设计模型。
结构图描述一个软件系统由哪些模块组成,以及模块之间的调用关系,结构图的基本成分有:模块、调用和数据
模块是指具有一定功能的可以用模块名调用的一组程序语句,包括函数和子程序。
调用(call):用从一个模块指向另一个模块的箭头来表示,其含义是前者调用了后者
为了方便,有时常用直线替代箭头,此时,表示位于上方的模块调用位于下方的模块
数据(data):模块调用时需传递的参数可通过在调用箭头旁附加一个小箭头和数据名来表示
结构图的三种调用表示:
DFD分为变换型结构和事务型结构两种
变换流
特征:数据流图可明显地分成三部分
输入:信息沿着输入路径进入系统,并将输入信息的外部形式经过编辑、格式转换、合法性检查、预处理等辅助性加工后变成内部形式
变换:内部形式的信息由变换中心进行处理
输出:然后沿着输出路径经过格式转换、组成物理块、缓冲处理等辅助性加工后变成输出信息送到系统外
事物流
特征:数据流沿着输入路径到达一个事务中心,事务中心
根据输入数据的类型在若干条动作路径中选择一条来执行 事务中心的任务是:接收输入数据(即事务);分析每个事务
的类型;根据事务类型选择执行一条动作路径
针对上述两种类型DFD,从DFD映射到SC也提出了两种类型,分别叫做变换映射和事物映射
变换映射
一般步骤如下:
划定输入流和输出流的边界,确定变换中心
进行第一级分解:将DFD映射成变换型的程序结构
进行第二级分解:将DFD中的加工映射成结构图中的一个适当的模块
标注输入输出信息:根据DFD,在初始结构图上标注模块之间传递的输入信息和输出信息
先举一个抽象的例子:
下面针对上述考务处理系统其中一个1层DFD图为例,来演示结构化设计的过程
这是第一步,任务是区分输入、输出和变换中心三个部分
下面要进行第一级分解:
在分解之前,我们可以先看一下对于一个任意的SC的框架,通常包含什么
对于一个任意的SC的框架通常包括最上面的两层模块------顶层和0层,任何系统的顶层都只含一个用于控制的主模块,它的下一层一般包括输入、输出、变换(控制)三个模块,分别对应SC的三个分支
因此对于上述的DFD变换映射的第二步(第一级分解)可以直接写成:
第三步:完成第二级分解,细化SC的各个分支。
对上步的结果继续进行由顶向下的分解,直至画出每个分支所需要的全部模块
可以好好对比下面两个图以加深理解
注意:从"加工"和"数据存储"中传递的数据在SC中有不同的体现,"数据存储"中传递的内容不用体现在SC上,比如"考生名册"传递给2.3和2.4的数据就没有体现
事务映射
与变换映射相似,事务映射也可以分为3个步骤
1.在DFD上确定事务中心、接收部分(包括输入路径)和发送部分(包括全部动作)
2.画出SC框架,把DFD的3个部分分别映射为事务控制模块、接受模块和动作发送模块,一般的SC框架如下所示:
3.分解和细化接受分支和发送分支,完成初始的SC,下面举一个抽象的例子:
优化结构设计
扇入和扇出:
扇入是指直接调用该模块的上级模块的个数。扇入大表示模块的复用程序高
扇出:是指该模块直接调用的下级模块的个数。扇出大表示模块的复杂度高,需要控制和协调过多的下级模块;但扇出过小(例如总是1)也不好。扇出过大一般是因为缺乏中间层次,应该适当增加中间层次的模块。扇出太小时可以把下级模块进一步分解成若干个子功能模块,或者合并到它的上级模块中去
比如左图的答案就是3
扇出过大的情况:
设计良好的软件通常具有瓮形结构,两头小,中间大,这类软件在下部收拢,表明它在底层模块中使用了较多高扇入的共享模块,比如下面这个图:
优化的另一个方法是:模块的作用域应限制在该模块的控制域范围内
先来介绍什么是作用域和控制域
一个模块的控制域是指该模块自身及其下级模块(即可供它调用的模块),比如说顶层模块的控制域是下面的全部模块(包含顶层模块自身)
一个模块的作用域是受这个模块中的判定所影响的模块,这个要看具体的情况,位置是不确定的,下面会举具体例子
上面是四种设计,其中带阴影的模块受带菱形的模块的影响,那么这四种设计哪一种最优呢?
先看a图,A受B2影响,但是A不在B2的控制域范围内(B2没有调用任何模块),所以这个设计是不好的
再看b图,A和B2受顶层模块Top的影响,也就是说Top的作用域确实在其控制域范围内,但存在一个问题:从决策控制模块到被控模块之间相差的层次太多
因此c、d图相对b要更好,其中d图是这四个设计中最优的选择
实例分析
还是以上面已经划过的SC为例:
第一步优化:减少耦合度
1.将"输入成绩清单"、"检查成绩清单"、"打印成绩单出错信息"合并成"输入并检查成绩清单"
2.将"输入合格标准"与"审定合格者"合并,仍取名"审定合格者",但它包含读入合格标准功能
3.将"产生考生通知单"与"打印考生通知单"合并成"产生并打印考生通知单"
第二步优化:模块的作用域应限制在该模块的控制域范围内
很容易发现,此时"打印难度分析表"、"打印分类统计表"分别受"分析试题难度"、"分类统计成绩"的影响,所以将"打印难度分析表"、"打印分类统计表"放在"分析试题难度"、"分类统计成绩"的控制域下面
第三步优化:删除多余模块
可以看出,此时"统计成绩输出控制"模块已经没有存在的意义了,删除即可
删除之后,发现"统计成绩输入控制"和"统计成绩处理模块"也没有存在的意义了,因为这两个模块的原来的意义在于为数据选择一个道路分支,但是由于只有把"统计成绩输出控制"删除之后只有一条路可以选择了,所以"统计成绩输入控制"和"统计成绩处理模块"就成了"管道模块",直接删除即可
详细设计(过程设计)
系统的详细设计就是对SC中的每个模块给出足够详细的过程性描述,常用的结构化详细设计的表达工具包括程序流程图、PAD图、N-S图和伪代码
本文重点对程序流程图做出注解
一个结构化的程序设计的程序流程图必须满足:是一种采用自顶向下逐步求精的设计方法和单入口单出口的控制结构
比如下面就不是结构化的:
通常所说的结构化程序,是按照狭义的结构程序的 定义衡量,符合定义规定的程序,每个代码块只有一个入口 和一个出口,上述这个图中圈起来的代码块(选择结构)中有两个入口,分别从C1过来和从A过来,所以是非结构化
改成结构化可以采用重复编码技术:
再举一个例子:
图示的程序的循环控制结构有两个出口,分别从p出和从q出。显然 不符合狭义的结构程序的定义,因此是非结构化的程序,可以修改为: