0、概述
结构化方法总的指导思想是自顶向下、逐层分解,它的基本原则是功能的分解与抽象。它是软件工程中最早出现的开发方法,特别适合于数据处理领域的问题,但是不适合解决大规模的、特别复杂的项目,且难以适应需求的变化。
一、系统分析与设计
1、系统分析一般过程
(1)认识、理解当前的现实环境,获得当前系统的“物理模型”
(2)从当前系统的“物理模型”抽象出当前系统的“逻辑模型”
(3)对当前系统的“逻辑模型”进行分析和优化,建立目标系统的“逻辑模型”
(4)对目标系统的逻辑模型具体化(物理化),建立目标系统的物理模型
系统开发的目的是把现有系统的物理模型转化为目标系统的物理模型,即图中双虚线所描述的路径,而系统分析阶段的结果是得到目标系统的逻辑模型.逻辑模型反映了系统的功能和性质,而物理模型反映的是系统的某一种具体实现方案.
2、系统设计基本原理
(1)抽象
(2)模块化
(3)信息隐藏
(4)模块独立。
衡量模块独立程度的标准:耦合性、内聚性。
【1】耦合
耦合是模块之间的相对独立性 (互相连接的紧密程度) 的度量。耦合取决于各个模块之间接口的复杂程度、调用模块的方式以及通过接口的信息类型等。一般模块之间可能的耦合方式有7种类型。
【顺口溜】由高到低 >>> 接数标致不共容
- 无直接耦合。指两个模块之间没有直接的关系,它们分别从属于不同模块的控制与调用,它们之间不传递任何信息。因此,模块间耦合性最弱,模块独立性最高。
- 数据耦合。指两个模块之间有调用关系,传递的是简单的数据值,相当于高级语言中的值传递。
- 标记耦合。指两个模块之间传递的是数据结构。
- 控制耦合。指一个模块调用另一个模块时,传递的是控制变量,被调用模块通过该控制变量的值有选择地执行模块内的某一功能。因此,被调用模块应具有多个功能,哪个功能起作用受调用模块控制。
- 外部耦合。模块间通过软件之外的环境联结(如 IO 将模块合到特定的设备、格式通信协议上) 时称为外部耦合。
- 公共耦合。指通过一个公共数据环境相互作用的那些模块间的耦合。
- 内容耦合。当一个模块直接使用另一个模块的内部数据,或通过非正常入口转入另个模块内部时,这种模块之间的耦合称为内容耦合。
【2】内聚
内聚是对一个模块内部各个元素彼此结合的紧密程度的度量。一个内聚程度高的模块(在理想情况下) 应当只做一件事。一般模块的内聚性分为 7 种类型。
【顺口溜】由弱到强 >>>> 欧罗使过信序能
- 偶然内聚(巧合内聚)。指一个模块内的各处理元素之间没有任何联系逻辑内聚。指模块内执行若干个逻辑上相似的功能,通过参数确定该模块完成哪一个功能。
- 时间内聚。把需要同时执行的动作组合在一起形成的模块称为时间内聚模块。
- 过程内聚。指一个模块完成多个任务,这些任务必须按指定的过程执行
- 通信内聚。指模块内的所有处理元素都在同一个数据结构上操作,或者各处理使用相同的输入数据或者产生相同的输出数据。
- 顺序内聚。指一个模块中的各个处理元素都密切相关于同一功能且必须顺序执行,前功能元素的输出就是下一功能元素的输入。
- 功能内聚。这是最强的内聚,指模块内的所有元素共同作用完成一个功能,缺一不可。
3、系统总体结构设计
系统总体结构设计是要根据系统分析的要求和组织的实际情况对新系统的总体结构形式和可利用的资源进行大致设计,这是一种宏观、总体上的设计和规划。
【1】系统结构设计原则
(1)分解-协调原则
(2)自顶向下的原则
(3)信息隐蔽、抽象的原则
(4)一致性原则
(5)明确性原则
(6)模块之间的耦合尽可能小,模块的内聚度尽可能高
(7)模块的扇入系数和扇出系数要合理
(8)模块的规模适当
【2】子系统划分原则
(1)子系统要具有相对独立性
(2)子系统之间数据的依赖性尽量小
(3)子系统划分的结果应使数据冗余较小
(4)子系统的设置应考虑今后管理发展的需要
(5)子系统的划分应便于系统分阶段实现
(6)子系统的划分应考虑到各类资源的充分利用
子系统结构设计的任务是确定划分后的子系统模块结构,并画出模块结构图。
【3】系统模块结构设计
模块是组成系统的基本单位,它的特点是可以组合、分解和更换。系统中的任何一个处理功能都可以看成是一个模块。根据功能具体化程度的不同,模块可以分为逻辑模块和物理模块。在系统逻辑模型中定义的处理功能可视为逻辑模块。物理模块是逻辑模块的具体化,可以是一个计算机程序、子程序或若干条程序语句,也可以是人工过程的某项具体工作。
一个模块应具备以下 4 个要素。
(1) 输入和输出。模块的输入来源和输出去向都是同一个调用者,即一个模块从调用者那里取得输入,进行加工后再把输出返回给调用者。
(2) 处理功能。指模块把输入转换成输出所做的工作。
(3) 内部数据。指仅供该模块本身引用的数据。
(4) 程序代码。指用来实现模块功能的程序。
前两个要素是模块外部特性,反映了模块的外貌。后两个要素是模块的内部特性。
二、结构化分析方法
结构化分析与设计方法是一种面向数据流的传统软件开发方法,它以数据流为中心构建软件的分析模型和设计模型。
结构化方法的分析结果由以下几部分组成:一套分层的数据流图、一本数据词典、一组小说明(也称加工逻辑说明)、补充材料。
1、数据流图
【1】基本元素
数据流图中的基本图形元素包括数据流(Data Flow)、加工(Process)、数据存储(Data Store)和外部实体(Extermal Agent)。其中,数据流、加工和数据存储用于构建软件系统内部的数据处理模型,外部实体表示存在于系统之外的对象,用来帮助用户理解系统数据的来源和去向。
1、数据流
数据流由一组固定成分的数据组成,表示数据的流向。在 DFD 中,数据流的流向可以有以下几种
- 从一个加工流向另一个加工
- 从加工流向数据存储(写)
- 从数据存储流向加工(读)
- 从外部实体流向加工(输入)
- 从加工流向外部实体(输出)
可以看出,数据流的流向必须要经过加工。另外,需注意,DFD 中描述的是数据流,而不是控制流。
2、加工
加工描述了输入数据流到输出数据流之间的变换。一个加工可以有多个输入数据流和多个输出数据流,但至少有一个输入数据流和一个输出数据流。数据流图中常见的 3 种错误:
- 有输入但是没有输出,称之为“黑洞”。
- 有输出但没有输入,称之为“奇迹”。
- 输入不足以产生输出,称之为“灰洞”。
3、数据存储
数据存储用来存储数据。可以有数据流流入数据存储,表示数据的写入操作;也可以有数据流从数据存储流出,表示数据的读操作;还可以用双向箭头的数据流指向数据存储,表示对数据的修改。
4、外部实体
外部实体是指存在于软件系统之外的人员或组织,它指出系统所需数据的发源地 (源)和系统所产生的数据的归宿地(宿)。
【2】扩充符号
在 DFD 中,一个加工可以有多个输入数据流和多个输出数据流,此时可以加上一些扩充符号来描述多个数据流之间的关系。
1、星号(*)
星号表示数据流之间存在“与”关系。如果是输入流则表示所有输入数据流全部到达后才能进行加工处理:如果是输出流则表示加工结束将同时产生所有的输出数据流。
2、加号(+)
加号表示数据流之间存在“或”关系。如果是输入流则表示其中任何一个输入数据流到达后就能进行加工处理:如果是输入流则表示加工处理的结果是至少产生其中一个输出数据流。
3、异或
异或表示数据流之间存在“互斥”关系。如果是输入流则表示当且仅当其中一个输入流到达后才能进行加工处理:如果是输出流则表示加工处理的结果是仅产生这些输出数据流中的一个。
【3】层次结构
根据自顶向下逐层分解的思想,可以将数据流图按照层次结构来绘制,每张图中的加工个数可大致控制在“7 加减 2”的范围内,从而构成一套分层数据流图。
1、层次结构
分层数据流图的顶层只有一张图,其中只有一个加工,代表整个软件系统,该加工描述了软件系统与外界之间的数据流,称为顶层图。
顶层图中的加工(即系统) 经分解后的图称为 0 层图,也只有一张。
处于分层数据流图最底层的图称为底层图,在底层图中,所有的加工不再进行分解。
分层数据流图中的其他图称为中间层,其中至少有一个加工(也可以是所有加工) 被分解成一张子图。
在整套分层数据流图中,凡是不再分解成子图的加工称为基本加工。
2、图和加工的编号
首先介绍父图和子图的概念。
如果某图 (记为A)中的某一个加工分解成一张子图(记为B),则称A是B的父图,B是A的子图。若父图中有n个加工,则它可以有 0~n 张子图,但每张子图只对应一张父图。
为了方便对图进行管理和查找,可以采用下列方式对 DFD 中的图和加工编号。
【1】顶层图中只有一个加工 (代表整个软件系统),该加工不必编号。
【2】0 层图中的加工编号分别为 1、2、3···。
【3】子图号就是父图中被分解的加工号。
【4】对于子图中加工的编号,若父图中的加工号为x的加工分解成某一子图,则该子图中的加工编号分别为 x1、x.2、x.3···。
【4】流图画法
1、画系统的输入和输出
系统的输入和输出用顶层图来描述,即描述系统从哪些外部实体接收数据流,以及系统发送数据流到哪些外部实体。
顶层图只有一个加工,即待开发的软件系统。顶层图中的数据流就是系统的输入/输出信息。顶层图中通常没有数据存储。
2、画系统的内部
将顶层图的加工分解成若千个加工,并用数据流将这些加工连接起来,使得顶层图中的输入数据经过若千个加工处理后变换成顶层图的输出数据流,这张图称为 0 层图。从一个加工画出一张数据流图的过程实际上就是对这个加工的分解。
(1)确定加工。这里的加工指的是父图中某加工分解而成的子加工,可以采用下面两种方法来确定加工。
【1】根据功能分解来确定加工。一个加工实际上反映了系统的一种功能,根据功能分解的原理,可以将一个复杂的功能分解成若干个较小的功能,每个较小的功能就是分解后的子加工。这种方法多应用于高层 DED 中加工的分解。
【2】根据业务处理流程确定加工。分析父图中待分解的加工的业务处理流程,流程中的每步都可能是一个子加工。特别要注意在业务流程中数据流发生变化或数据流的值发生变化的地方,应该存在一个加工,该加工将原数据流 (作为该加工的输入数据流) 处理成变化后的数据流(作为该加工的输出数据流)。该方法较多应用于低层 DFD 中加工的分解,它能描述父加工中输入数据流到输出数据流之间的加工细节。
(2)确定数据流。当用户把若干个数据看作一个整体来处理(这些数据一起到达,一起加工)时,可以把这些数据看成一个数据流。通常,实际工作环境中的表单就是一种数据流。
在父图中某加工分解而成的子图中,父图中相应加工的输入/输出数据流就是子图边界上的输入/输出数据流。另外,在分解后的子加工之间应增添一些新的数据流,这些数据流是加工过程中的中间数据(对某子加工输入数据流的改变),它们与所有的子加工一起完成了父图中相应加工的输入数据流到输出数据流的变换。如果某些中间数据需要保存,以备使用,那么可以表示为流向数据存储的数据流。
同一个源或加工可以有多个数据流流向另一个加工,如果它们不是一起到达和一起加工的,那么可以将它们分成多个数据流。同样,同一个加工也可以有多个数据流流向另一个加工或宿。
(3) 确定数据存储。在由父图中某加工分解而成的子图中,如果父图中该加工存在流向数据存储的数据流(写操作),或者存在从数据存储流向该加工的数据流(读操作),则这种数据存储和相关的数据流都画在子图中。
在分解的子图中,如果需要保存某些中间数据,以备以后使用,那么可以将这些数据组成个新的文件。在自顶向下画分层数据流图时,新数据存储(首次出现的) 至少应有一个加工为其写入记录,同时至少存在另一个加工读取该数据存储的记录。
注意,对于从父图中继承下来的数据存储,在子图中可能只对其读记录,或者写记录。
(4)确定源和宿。通常在 0 层图和其他子图中不必画出源和宿,有时为了提供可读性,可以将顶层图中的源和宿画在 0 层图中。
当同一个外部实体(人或组织) 既是系统的源,又是系统的宿时,可以用同一个图形符号来表示。为了画图的方便,避免图中线的交叉,同一个源或宿可以重复画在 DFD 的不同位置以增加可读性,但它们仍代表同一个实体。
3、画加工的内部
当 DFD 中存在某个比较复杂的加工时,可以将它分解成一张 DFD 子图。分解的方法是将该加工看作一个小系统,该加工的输入/输出数据流就是这个假设的小系统的输入/输出数据流,然后采用画 0 层图的方法画出该加工的子图。
【5】流图审查
在分层数据流图画好后,应该认真检查图中是否存在错误或不合理 (不理想) 的部分。
1、分层数据流图的一致性和完整性
分层数据流图的一致性是指分层DFD 中不存在矛盾和冲突。这里讲的完整性是指分层DFD本身的完整性,即是否有遗漏的数据流、加工等元素。所以,分层 DED 的一致性和完整性实际上反映了图本身的正确性。但是图本身的正确性并不意味着分析模型的正确性,分析模型的正确性要根据模型是否满足用户的需求来判断。
(1) 分层数据流图的一致性
【1】父图与子图的平衡。父图与子图平衡是指任何一张 DFD 子图边界上的输入/输出数据流必须与其父图中对应加工的输入/输出数据流保持一致。
由于一张子图是被分解的加工的一种细化,所以,这张子图应该保证可以画到父图中替代被分解的加工,因此保持父图与子图平衡是理所当然的。
【2】数据守恒。数据守恒包括两种情况:
第一种情况是指一个加工的所有输出数据流中的数据必须能从该加工的输入数据流中直接获得,或者能通过该加工的处理而产生。
第二种情况是加工未使用其输入数据流中的某些数据项。这表明这些未用到的数据项是多 余的,可以从输入数据流中删去。当然,这不一定就是错误,只表示存在一些无用数据。然而这些无用的数据常常隐含着一些潜在的错误,如加工的功能描述不完整、遗漏或不完整的输出数据流等。因此,在检查数据守恒时,不应该忽视对这种情况的检查。
【3】 局部数据存储。
在一套完整的分层 DFD 中,任何一个数据存储都应有写和读的数据流,否则这个文件就没有存在的必要。除非这个数据存储的建立是为另一个软件系统使用或者这个数据存储是由另一个软件系统产生和维护的。
在自顶向下分解加工的过程中,如果某个加工需要保存一些数据,同时在将加工的同一张DFD 上至少存在另一个加工需要读这些数据,那么该数据存储应该在这张 DED 上画出。也就是在一张 DFD 中,当一个数据存储作为多个加工之间的交界面时,该数据存储应该画出。如果在一张 DFD 中,一个数据存储仅与一个加工进行读/写操作,并且在该 DFD 的父(祖先)图中未出现过该数据存储,那么该数据存储只是相应加工的内部文件,在这张 DFD 中不应该画出。
【4】一个加工的输出数据流不能与该加工的输入数据流同名。同一个加工的输出数据流和输入数据流,即使它们的组成成分相同,仍应该给它们取不同的名字,以表示它们是不同的数据流。但是允许一个加工有两个相同的数据流分别流向两个不同的加工。
(2) 分层数据流图的完整性。
【1】每个加工至少有一个输入数据流和一个输出数据流。一个没有输入数据流或者没有输出数据流的加工通常是没有意义的。当出现这种情况时,常常意味着可能遗漏了某些输入数据流或输出数据流。
【2】在整套分层数据流图中,每个数据存储应至少有一个加工对其进行读操作,另一个加工对其进行写操作。对于某一张 DFD 来说,可以只写不读或只读不写。
【3】分层数据流图中的每个数据流和文件都必须命名(除了流入或流出数据存储的数据流),并保持与数据字典一致。
【4】分层数据流图中的每个基本加工都应有一个加工规约。
2、构造分层 DFD 时需要注意的问题
(1) 适当命名。DFD 中的每个数据流、加工、数据存储、外部实体都应被适当地命名,名字应符合被命名对象的实际含义。通常,数据流名可用名词或形容词加名词来描述;加工名可以用动词或及物动词加宾语来描述: 数据存储名可以用名词来描述:外部实体可以用实际的人员身份或组织的名称来命名。
(2) 画数据流而不是控制流。数据流图强调的是数据流,而不是控制流。在 DFD 中一般不能明显地看出其执行的次序。为了区分数据流和控制流,可以简单地回答下列问题:“这条线上是否有数据流过?”,如果有表示是数据流,否则是控制流。
(3) 避免一个加工有过多的数据流。当一个加工有过多的数据流时,意味着这个加工特别复杂,这往往是分解不合理的表现。解决的办法是重新分解,步骤如下
- 把需要重新分解的某张图的所有子图连接成一张图。
- 把连接后的图重新划分成几个部分,使各部分之间的联系最小。
- 重新定义父图,即第2步中的每个部分作为父图中的一个加工。
- 重新建立各子图,即第2步中的每个部分都是一张子图。
- 为所有的加工重新命名并编号。
(4) 分解尽可能均匀。理想的分解是将一个问题(加工) 分解成大小均匀的若干个子问题(子加工),也就是说,对于任何一张 DFD,其中的任何两个加工的分解层数之差不超过 1。如果在同一张图中,某些加工已是基本加工,而另一些加工仍需分解若干层,那么,这张图就是分解不均匀的。
(5) 先考虑确定状态,忽略琐碎的细节。在构造 DFD 时,应集中精力先考虑稳定状态下的各种问题,暂时不考虑系统如何自动、如何结束、出错处理以及性能等问题,这些问题可以在分析阶段的后期,在需求规约中加以说明。
(6) 随时准备重画。对于一个复杂的软件系统,其分层 DFD 很难一次开发成功,往往要经历反复多次的重画和修改,才能构造出完整、合理、满足用户需求的分层 DFD。
3、分解的程度
在自顶向下画数据流图时,为了便于对分解层数进行把握,可以参照以下几条与分解有关的原则。
(1) 7 加减 2。
(2) 分解应自然,概念上应合理、清晰。
(3) 只要不影响 DFD 的易理解性,可适当增加子加工数量,以减少层数。
(4) 一般来说,上层分解得快一些(即多分解几个加工),下层分解得慢一些 (即少分解几个加工)。
(5) 分解要均匀
2、数据字典
数据流图描述了系统的分解,但没有对图中各成分进行说明。数据字典就是为数据流图中的每个数据流、文件、加工,以及组成数据流或文件的数据项做出说明。
【1】内容
数据字典有以下 4 类条目:数据流、数据项、数据存储和基本加工。
【2】管理
词典管理主要是把词典条目按照某种格式组织后存储在词典中,并提供排序、查找和统计等功能。
【3】描述
加工逻辑也称为“小说明”。常用的加工逻辑描述方法有结构化语言、判定表和判定树3 种。
《1》结构化语言
结构化语言是一种介于自然语言和形式化语言之间的半形式化语言。其结构通常可分为内层和外层。外层有严格的语法,内层的语法比较灵活,可以接近于自然语言的描述。
(1) 外层。用来描述控制结构,采用顺序、选择和重复 3 种基本结构。
顺序结构。一组祈使语句、选择语句、重复语句的顺序排列。祈使语句是指至少包含一个动词及一个名词,指出要执行的动作及接受动作的对象。
选择结构。一般用IF-THEN-ELSE-ENDIF、CASE-OF-ENDCASE 等关键词。
重复结构。一般用 DO-WHILE-ENDDO、REPEAT-UNTIL 等关键词。
(2)内层。一般采用祈使语句的自然语言短语,使用数据字典中的名词和有限的自定义词,其动词含义要具体,尽量不用形容词和副词来修饰,还可使用一些简单的算法运算和逻辑运算符号。
《2》判定表
在有些情况下,数据流图中某个加工的一组动作依赖于多个逻辑条件的取值。这时,用自然语言或结构化语言都不易于清楚地描述出来,而用判定表能够清楚地表示复杂的条件组合与应做的动作之间的对应关系。
《3》判定树
判定树是判定表的变形,一般情况下它比判定表更直观,且易于理解和使用。
3、结构化设计方法
结构化设计SD方法是一种面向数据流的设计方法,它可以与SA方法衔接。结构化设计方法的基本思想是将系统设计成由相对独立、功能单一的模块组成的结构。
结构化设计方法中用结构图来描述软件系统的体系结构,指出一个软件系统由哪些模块组成,以及模块之间的调用关系。
结构化设计主要包括
(1)体系结构设计:定义软件的主要结构元素及其关系
(2)数据设计:基于实体联系图确定软件涉及的文件系统的结构及数据库的表结构,
(3)接口设计:描述用户界面,软件和其他硬件设备、其他软件系统及使用人员的外部接口,以及各种构件之间的内部接口。
(4)过程设计:确定软件各个组成部分内的算法及内部数据结构,并选定某种过程的表达形式来描述各种算法。