第四章 总体设计
可行性分析 -- Why? Who? 需求分析 -- What? 设计 -- How do? 总体设计 (概要设计)确定软件的结构以及 各组成成分(子系统或模块)之间的相互关系 设计 详细设计确定模块内部的算法和数据结构, 产生描述各模块程序过程的详细文档。
总体设计的任务 划分出组成系统的物理元素—程序、文件、数据库、人工过程和文档等,但是每个物理元素仍然处于黑盒子级,这些黑盒子里的具体内容将在以后仔细设计。 设计软件的结构,也就是要确定系统中每个程序是由哪些模块组成的,以及这些模块相互间的关系。
总体设计的必要性 可以站在全局高度上,花较少成本,从较抽象的层次上分析对比多种可能的系统实现方案和软件结构,从中选出最佳方案和最合理的软件结构,从而用较低成本开发出较高质量的软件系统
4.1 设计过程 总体设计过程通常由两个主要阶段组成: -- 系统设计阶段,确定系统具体实现方案; -- 结构设计阶段,确定软件结构。
典型的总体设计过程包括下述9个步骤: 1. 设想供选择的方案 2. 选取合理的方案 3. 推荐最佳方案 4. 功能分解 5. 设计软件结构 6. 设计数据库 7. 制定测试计划 8. 书写文档 9. 审查和复审
总体设计所书写的文档 总体设计说明 --系统流程图描绘的系统构成方案,组成系统的物理元素清单,成本/效益分析; --对最佳方案的概括描述,精化的数据流图,用层次图或结构图描绘的软件结构,用IPO图或其他工具简要描述的各个模块的算法,模块间的接口关系,以及需求、功能和模块三者之间的交叉参照关系等等。
总体设计所书写的文档 (2) 用户手册 根据总体设计阶段的结果,修改更正在需求分析阶段产生的初步的用户手册。 (3) 测试计划 包括测试策略,测试方案,预期的测试结果,测试进度计划等等。 (4) 详细的实现计划 (5) 数据库设计结果
概要设计说明书(GB8567—88)
4.2 设计原理 模块化 抽 象 逐步求精 信息隐藏和局部化 模块独立
4.2.1 模块化 模块是由边界元素限定的相邻程序元素(例如,数据说明,可执行的语句)的序列,而且有一个总体标识符代表它。 4.2.1 模块化 模块是由边界元素限定的相邻程序元素(例如,数据说明,可执行的语句)的序列,而且有一个总体标识符代表它。 -- 如:过程、函数、子程序、宏、对象等,都可作为模块。 模块化就是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足用户的需求。
模块该如何划分? 设:C(x)为复杂程度函数 E(x)为决定解决问题x所需的 工作量(时间)函数 对于两个问题P1和P2, 如果 C(P1)>C(P2) 则: E(P1)>E(P2) 如果 C(P1+P2)>C(P1)+C(P2) 则: E(P1+P2)>E(P1)+E(P2) 这个不等式导致“各个击破”的结论—把复杂的问题分解成许多容易解决的小问题,原来的问题也就容易解决了。这就是模块化的根据。 最小成本区 M 模块成本 接口成本 总成本 软件 开发 工作 量 模块数
人类在认识复杂现象的过程中使用的最强有力的思维工具是抽象。 -- 就是抽出事物的本质特性(共性),而暂时不考虑它们的细节。 4.2.2 抽象 人类在认识复杂现象的过程中使用的最强有力的思维工具是抽象。 -- 就是抽出事物的本质特性(共性),而暂时不考虑它们的细节。
处理复杂系统的惟一有效的方法是用层次的方式构造和分析它。 4.2.2 抽象 处理复杂系统的惟一有效的方法是用层次的方式构造和分析它。 -- 在抽象的最高层次使用问题环境的语言,以概括的方式叙述问题的解法; -- 在较低抽象层次采用更过程化的方法,把面向问题的术语和面向实现的术语结合起来叙述问题的解法; --最后在最低的抽象层次用可直接实现的方式叙述问题的解法。
软件工程过程的每一步都是对软件解法的抽象层次的一次精化。 4.2.2 抽象 软件工程过程的每一步都是对软件解法的抽象层次的一次精化。 --可行性研究阶段,软件作为系统的一个完整部件 --需求分析期间,软件解法是使用在问题环境内熟 悉的方式描述的 --由总体设 计向详细设计过渡时,抽象的程度也就随之减少了 --当源程序写出来以后,也就达到了抽象的最低层
4.2.3 逐步求精 逐步求精是人类解决复杂问题时采用的基本方法,也是许多软件工程技术(例如,规格说明技术,设计和实现技术)的基础。 4.2.3 逐步求精 逐步求精是人类解决复杂问题时采用的基本方法,也是许多软件工程技术(例如,规格说明技术,设计和实现技术)的基础。 逐步求精定义为:“为了能集中精力解决主 要问题而尽量推迟对问题细节的考虑。”
4.2.3 逐步求精 逐步求精最初是由Niklaus Wirth提出的一种自顶向下的设计策略。 他本人的概括说明如下: 4.2.3 逐步求精 逐步求精最初是由Niklaus Wirth提出的一种自顶向下的设计策略。 他本人的概括说明如下: 我们对付复杂问题的最重要的办法是抽象,因此,对一个复杂的问题不应该立刻用计算机指令、数字和逻辑符号来表示,而应该用较自然的抽象语句来表示,从而得出抽象程序。抽象程序对抽象的数据进行某些特定的运算并用某些合适的记号(可能是自然语言)来表示。对抽象程序做进一步的分解,并进入下一个抽象层次,这样的精细化过程一直进行下去,直到程序能被计算机接受为止。这时的程序可能是用某种高级语言或机器指令书写的。
求精则帮助设计者在设计过程中逐步揭示出低层细节。 抽象与求精是一对互补的概念。 抽象使得设计者能够说明过程和数据,同时 却忽略低层细节。事实上,可以把抽象看作是一种通过忽略多余的细节同时强调有关的细节,而实现逐步求精的方法。 求精则帮助设计者在设计过程中逐步揭示出低层细节。 这两个概念都有助于设计者在设计演化过程中创造出完整的设计模型。
4.2.4 信息隐藏和局部化 信息隐藏原理指出:设计和确定模块,使得一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是不能访问的。 局部化的概念和信息隐藏概念是密切相关的。 所谓局部化:是指把一些关系密切的软件元素物理地放得彼此靠近。 -- 在模块中使用局部数据元素是局部化的一个例子。显然,局部化有助于实现信息隐藏。 如果在测试期间和以后的软件维护期间需要修改软件,那么使用信息隐藏原理作为模块化系统设计的标准就会带来极大好处。
4.2.5 模块独立 涉及软件要求的具体的子功能,而和软件系统 中其他模块的接口是简单的。 模块的独立程度可以由两个定性标准度量 耦合 内聚 4.2.5 模块独立 模块的独立性是指软件系统中每个模块只 涉及软件要求的具体的子功能,而和软件系统 中其他模块的接口是简单的。 模块的独立程度可以由两个定性标准度量 耦合 内聚 模块之间的 相对独立性 的度量 模块功能强 度的度量
1. 耦合 它取决于各个模块之间接口的复杂程度、调用模块的方 式以及那些信息通过接口。 低 耦合性 强 模块独立性 弱 1. 耦合 耦合性是程序结构中各个模块之间相互关联的度量 它取决于各个模块之间接口的复杂程度、调用模块的方 式以及那些信息通过接口。 低 耦合性 高 非直接 耦合 数据 标记 控制 外部 公共 内容 强 模块独立性 弱
(1) 非直接耦合 两个模块没有直接关系(模块1和模块2), 模块独立性最强。 模块2 模块1 模块3 模块4
一模块调用另一模块时,被调用模块的输入、输出都是简单的数据(若干参数)。 (2) 数据耦合 一模块调用另一模块时,被调用模块的输入、输出都是简单的数据(若干参数)。 属松散耦合。 开发票 单价 数量 金额 计算水费
(3) 标记耦合(特征耦合) 如两个模块通过传递数据结构(不是简单数据,而是记录、数组等)加以联系,或都与一个数据结构有关系, 则称这两个模块间存在标记偶合。 计算电费 住户情况 住户情况 水费 电费 计算水费 计算水电费 “住户情况”是一个数据结构,图中模块都与此数据结构有关.“计算水费”和“计算电费”本无关,由于引用了此数据结构产生依赖关系,它们之间也是标记偶合.
(4) 控制耦合 如果一个模块通过传送开关、标志、名字 等控制信息,明显地控制选择另一模块的功能 就是控制耦合。 A 模块 B 如果一个模块通过传送开关、标志、名字 等控制信息,明显地控制选择另一模块的功能 就是控制耦合。 A 模块 flag f1 B f2 fn … … 控制耦合增加了理解和编程的复杂性,调用模块必须知道被调模块的内部逻辑,增加了相互依赖。 去除模块间控制耦合的方法: (1)将被调用模块内的判定上移到调用模块中进行 (2)被调用模块分解成若干单一功能模块
(5) 外部耦合 一组模块均与同一外部环境关联(例如, I/O模块与特定的设备、格式和通信协议相关联),它们之间便存在外部耦合。 外部偶合必不可少,但这种模块数目应尽量少。
(6) 公共环境耦合(公共数据区耦合) 公共数据区指: 全局数据结构 共享通讯区 内存公共覆盖区等 全局常量的好处: (1)软件可理解性提高 一组模块引用同一个公用数据区(也称全局数据区、公共数据环境)。 公共数据区指: 全局数据结构 共享通讯区 内存公共覆盖区等 A B C 公共数据区 全局常量的好处: (1)软件可理解性提高 (2)软件可维护性增强
最不好的耦合形式! (7) 内容耦合 A B 一模块直接访问另一模块的内部信息 (程序代码或数据) 模块代码重叠 多入口模块 A B Entry1 …… Entry2 A B A B 一模块直接访问另一模块的内部信息 (程序代码或数据) 模块代码重叠 不正常转入另一模块 多入口模块 最不好的耦合形式!
以上给出了 7种耦合类型,这只是从耦合的机制上所做的分类,按耦合的强弱程度的排列只是相对的关系。但它给设计人员在设计程序结构时提供了一决策准则。实际上,开始时两个模块之间的耦合不只是一种类型,而是多种类型的混合。这就要求设计人员按照实际情况进行分析、比较和分析,逐步加以改进,以提高模块的独立性。
总之,耦合是影响软件复杂程度的一个重要因素。应该采取下述设计原则: 尽量使用数据耦合,少用控制耦合和特征耦合,限制公共环境耦合的范围,完全不用内容耦合。
2. 内 聚 一个模块内部元素在功能上相互关联的强度 设计目标:高内聚,模块在软件过程中完成单一的任务
(1) 功能内聚 一个模块中各个部分都是完成某一具体功能必不可少的组成部分,或者说该模块中所有部分都是为了完成一项具体功能而协同工作,紧密联系,不可分割的。则称该模块为功能内聚模块。 内聚性最强
(2) 信息内聚 这种模块完成多个功能,各个功能都在同一数据结构上操作,每一项功能有一个唯一的入口点。这个模块将根据不同的要求,确定该执行哪一个功能。由于这个模块的所有功能都是基于同一个数据结构(符号表),因此,它是一个信息内聚的模块。 信息内聚模块可以看成是多个功能内聚模块的组合,并且达到信息的隐蔽。即把某个数据结构、资源或设备隐蔽在一个模块内,不为别的模块所知晓
(3) 通信内聚 如果一个模块内各功能部分都使用了相同的输入数据,或产生了相同的输出数据,则称之为通信内聚模块。通常,通信内聚模块是通过数据流图来定义的。
读入 成绩单 审查 成绩单 统计 成绩 打印 成绩 (4) 过程内聚 模块内各处理成分相关,且必须以特定次序执行 读入并审查成绩单 统计并打印成绩单
(5) 时间内聚 时间内聚又称为经典内聚。这种模块大多为多功能模块,但模块的各个功能的执行与时间有关,通常要求所有功能必须在同一时间段内执行。 例如初始化模块和终止模块,系统结束模块、紧急故障处理模块等均是时间性聚合模块 。
把几种相关功能(逻辑上相似的功能)组合在一模块内,每次调用由传给模块的参数确定执行哪种功能。 (6) 逻辑内聚 把几种相关功能(逻辑上相似的功能)组合在一模块内,每次调用由传给模块的参数确定执行哪种功能。 S X Y Z W A B C D 若一个模块完成的任务在逻辑上相同或相似,如X,Y,Z,W分别调用A,B,C,D,而模块 A,B,C,D确完成的任务相似(如产生各种类型的全部输出),则我们把A,B,C,D 合并成一个模块ABCD,那么我们称模块ABCD就是逻辑模块 S X Y Z W ABCD
(7) 巧合内聚 当模块内各部分之间没有联系,或者即使有联系,这种联也很松散,则称这种模块为巧合内聚模块,它是内聚程度最低的模块。 模块M中的三个语句没有任何联系 缺点:可理解性差, 可修改性差
力争强内聚、弱耦合 内聚与耦合密切相关,同其它模块强耦合的 模块意味者弱内聚,强内聚模块意味着与其它模块间松散耦合。 设计目标: 耦合、内聚与模块独立性关系: 耦合与内聚都是模块独立性的定性标准,都反映模块独立性的良好程度。但耦合是直接的主导因素,内聚则辅助耦合共同对模块独立性进行衡量。
4.3 启发规则 改进软件结构提高模块独立性。 模块规模应该适中。 深度、宽度、扇出和扇入都应适当。 模块的作用域应该在控制域之内。 4.3 启发规则 改进软件结构提高模块独立性。 模块规模应该适中。 深度、宽度、扇出和扇入都应适当。 模块的作用域应该在控制域之内。 5. 力争降低模块接口的复杂程度。 6. 设计单入口单出口的模块。 7. 模块功能应该可以预测。 人们在开发计算机软件的长期实践中积累了丰富的经验,总结这些经验得出了一些启发式规则。这些启发式规则虽然不像上一节讲述的基本原理和概念那样普遍适用,但是在许多场合仍然能给软件工程师以有益的启示,往往能帮助他们找到改进软件设计提高软件质量的途径。下面介绍几条启发式规则。 1. 改进软件结构提高模块独立性 设计出软件的初步结构以后,应该审查分析这个结构,通过模块分解或合并,力求降低耦合提高内聚。例如,多个模块公有的一个子功能可以独立成一个模块,由这些模块调用;有时可以通过分解或合并模块以减少控制信息的传递及对全程数据的引用,并且降低接口的复杂程度。 2. 模块规模应该适中 经验表明,一个模块的规模不应过大,最好能写在一页纸内(通常不超过60行语句)。有人从心理学角度研究得知,当一个模块包含的语句数超过30以后,模块的可理解程度迅速下降。 过大的模块往往是由于分解不充分,但是进一步分解必须符合问题结构,一般说来,分解后不应该降低模块独立性。 过小的模块开销大于有效操作,而且模块数目过多将使系统接口复杂。因此过小的模块有时不值得单独存在,特别是只有一个模块调用它时,通常可以把它合并到上级模块中去而不必单独存在。 3. 深度、宽度、扇出和扇入都应适当 深度表示软件结构中控制的层数,它往往能粗略地标志一个系统的大小和复杂程度。深度和程序长度之间应该有粗略的对应关系,当然这个对应关系是在一定范围内变化的。如果层数过多则应该考虑是否有许多管理模块过分简单了,能否适当合并。 宽度是软件结构内同一个层次上的模块总数的最大值。一般说来,宽度越大系统越复杂。对宽度影响最大的因素是模块的扇出。 扇出是一个模块直接控制(调用)的模块数目,扇出过大意味着模块过分复杂,需要控制和协调过多的下级模块;扇出过小(例如总是1)也不好。经验表明,一个设计得好的典型系统的平均扇出通常是3或4(扇出的上限通常是5~9)。 扇出太大一般是因为缺乏中间层次,应该适当增加中间层次的控制模块。扇出太小时可以把下级模块进一步分解成若干个子功能模块,或者合并到它的上级模块中去。当然分解模块或合并模块必须符合问题结构,不能违背模块独立原理。 一个模块的扇入表明有多少个上级模块直接调用它,扇入越大则共享该模块的上级模块数目越多,这是有好处的,但是,不能违背模块独立原理单纯追求高扇入。 观察大量软件系统后发现,设计得很好的软件结构通常顶层扇出比较高,中层扇出较少,底层扇入到公共的实用模块中去(底层模块有高扇入)。 4. 模块的作用域应该在控制域之内 模块的作用域定义为受该模块内一个判定影响的所有模块的集合。模块的控制域是这个模块本身以及所有直接或间接从属于它的模块的集合。例如,在图5.2中模块A的控制域是A、B、C、D、E、F等模块的集合。 在一个设计得很好的系统中,所有受判定影响的模块应该都从属于做出判定的那个模块,最好局限于做出判定的那个模块本身及它的直属下级模块。 5. 力争降低模块接口的复杂程度 模块接口复杂是软件发生错误的一个主要原因。应该仔细设计模块接口,使得信息传递简单并且和模块的功能一致。 接口复杂或不一致(即看起来传递的数据之间没有联系),是紧耦合或低内聚的征兆,应该重新分析这个模块的独立性。 6. 设计单入口单出口的模块 这条启发式规则警告软件工程师不要使模块间出现内容耦合。当从顶部进入模块并且从底部退出来时,软件是比较容易理解的,因此也是比较容易维护的。 7. 模块功能应该可以预测 模块的功能应该能够预测,但也要防止模块功能过分局限。 如果一个模块可以当做一个黑盒子,也就是说,只要输入的数据相同就产生同样的输出,这个模块的功能就是可以预测的。带有内部“存储器”的模块的功能可能是不可预测的,因为它的输出可能取决于内部存储器(例如某个标记)的状态。由于内部存储器对于上级模块而言是不可见的,所以这样的模块既不易理解又难于测试和维护。 如果一个模块只完成一个单独的子功能,则呈现高内聚;但是,如果一个模块任意限制局部数据结构的大小,过分限制在控制流中可以做出的选择或者外部接口的模式,那么这种模块的功能就过分局限,使用范围也就过分狭窄了。在使用过程中将不可避免地需要修改功能过分局限的模块,以提高模块的灵活性,扩大它的使用范围;但是,在使用现场修改软件的代价是很高的。 以上列出的启发式规则多数是经验规律,对改进设计,提高软件质量,往往有重要的参考价值;但是,它们既不是设计的目标也不是设计时应该普遍遵循的原理。
4.4 软件设计过程 1. 制定规范 在进入软件开发阶段之初,首先应为软件开发组制定在设计时应该共同遵守的标准,以便协调组内各成员的工作。包括: -- 阅读和理解软件需求说明书,确认用户要求能否实现,明确实现的条件,从而确定设计的目标,以及它们的优先顺序 -- 根据目标确定最合适的设计方法 -- 规定设计文档的编制标准 -- 规定编码的信息形式,与硬件,操作系统的接口规约,命名规则
4.4 软件设计过程 2. 软件系统结构的总体设计 基于功能层次结构建立系统 -- 采用某种设计方法,将系统按功能划分成模块的层次结构 4.4 软件设计过程 2. 软件系统结构的总体设计 基于功能层次结构建立系统 -- 采用某种设计方法,将系统按功能划分成模块的层次结构 -- 确定每个模块的功能 -- 建立与已确定的软件需求的对应关系 -- 确定模块间的调用关系 -- 确定模块间的接口 -- 评估模块划分的质量
4.4 软件设计过程 3. 处理方式设计 确定为实现系统的功能需求所必需的算法,评估算法的性能 4.4 软件设计过程 3. 处理方式设计 确定为实现系统的功能需求所必需的算法,评估算法的性能 确定为满足系统的性能需求所必需的算法和模块间的控制方式 周转时间 响应时间 吞吐量 精度 确定外部信号的接收发送形式
4.4 软件设计过程 4. 数据结构设计 确定软件涉及的文件系统的结构以及数据库的模式、子模式,进行数据完整性和安全性的设计 4.4 软件设计过程 4. 数据结构设计 确定软件涉及的文件系统的结构以及数据库的模式、子模式,进行数据完整性和安全性的设计 确定输入,输出文件的详细的数据结构 结合算法设计,确定算法所必需的逻辑数据结构及其操作 确定对逻辑数据结构所必需的那些操作的程序模块(软件包)
4.4 软件设计过程 4. 数据结构设计(续) 限制和确定各个数据设计决策的影响范围 4.4 软件设计过程 4. 数据结构设计(续) 限制和确定各个数据设计决策的影响范围 若需要与操作系统或调度程序接口所必须的控制表等数据时,确定其详细的数据结构和使用规则 数据的保护性设计 防卫性设计:在软件设计中就插入自动检错,报错和纠错的功能
4.4 软件设计过程 一致性设计: 保证软件运行过程中所使用的数据的类型和取值范围不变 4.4 软件设计过程 一致性设计: 保证软件运行过程中所使用的数据的类型和取值范围不变 在并发处理过程中使用封锁和解除封锁机制保持数据不被破坏 冗余性设计: 数据库设计中的以空间换时间的处理方式。
4.4 软件设计过程 5.可靠性设计 可靠性设计也叫做质量设计 4.4 软件设计过程 5.可靠性设计 可靠性设计也叫做质量设计 在运行过程中,为了适应环境的变化和用户新的要求,需经常对软件进行改造和修正。在软件开发的一开始就要确定软件可靠性和其它质量指标,考虑相应措施,以使得软件易于修改和易于维护。
4.4 软件设计过程 6.编写概要设计阶段的文档 概要设计阶段完成时应编写以下文档: 概要设计说明书 数据库设计说明书 制定初步的测试计划
4.4 软件设计过程 7.概要设计评审 可追溯性:确认该设计是否复盖了所有已确定的软件需求,软件每一成份是否可追溯到某一项需求 4.4 软件设计过程 7.概要设计评审 可追溯性:确认该设计是否复盖了所有已确定的软件需求,软件每一成份是否可追溯到某一项需求 接口:确认该软件的内部接口与外部接口是否已经明确定义。模块是否满足高内聚和低耦合的要求。模块作用范围是否在其控制范围之内 风险:确认该设计在现有技术条件下和预算范围内是否能按时实现 实用性:确认该设计对于需求的解决方案是否实用
4.4 软件设计过程 7.概要设计评审 技术清晰度:确认该设计是否以一种易于翻译成代码的形式表达 4.4 软件设计过程 7.概要设计评审 技术清晰度:确认该设计是否以一种易于翻译成代码的形式表达 可维护性:确认该设计是否考虑了方便未来的维护 质量:确认该设计是否表现出良好的质量特征 各种选择方案:看是否考虑过其它方案,比较各种选择方案的标准是什么 限制:评估对该软件的限制是否现实,是否与需求一致 其它具体问题:对于文档、可测试性、设计过程等进行评估
5.5 描绘软件结构的图形工具 1、层次图和HIPO图 IBM公司发明的HIPO图: 层次图 + 输入 / 处理 /输出图 5.5 描绘软件结构的图形工具 1、层次图和HIPO图 IBM公司发明的HIPO图: 层次图 + 输入 / 处理 /输出图 (H图) (IPO图) (Hiberarchy Input Process Output)
正文加工系统的层次图
2、结构图(SC -- Structure Chart) Yourdon提出的结构图是进行软件结构设计的另一个有力工具。结构图和层次图类似,也是描绘软件结构的图形工具。 结构图反映程序中模块之间的层次调用关系和联系:它以特定的符号表示模块、模块间的调用关系和模块间信息的传递。
① 模块:模块用矩形框表示,并用模块的名字标记它。
② 模块的调用关系和接口:模块之间用单向箭头联结,箭头从调用模块指向被调用模块
③ 模块间的信息传递:当一个模块调用另一个模块时,调用模块把数据或控制信息传送给被调用模块,以使被调用模块能够运行。而被调用模块在执行过程中又把它产生的数据或控制信息回送给调用模块。
④ 在模块A的箭头尾部标以一个菱形符号,表示模块A有条件地调用另一个模块B。当一个在调用箭头尾部标以一个弧形符号,表示模块A反复调用模块C和模块D。
程序的系统结构图
4.6 面向数据流的设计方法 --- 结构化设计(SD - Structured Design) 面向数据流的设计方法的目标是给出设计软件结构的一个系统化的途径。 面向数据流的设计要解决的任务,就是在需求分析的基础上,将表示系统逻辑模型的DFD图映射(Mapping)成软件系统结构的初始设计描述。 SD 目标系统的DFD 目标系统的SC
结构化设计方法(SD) 1)首先研究、分析和审查数据流图。 从软件的需求规格说明中弄清数据流加工的过程,对于发现的问题及时解决。 2)然后根据数据流图决定问题的类型。数据处理问题典型的类型有两种:变换型和事务型。针对两种不同的类型分别进行分析处理。 3)由数据流图推导出系统的初始结构图。 4)利用一些启发式原则来改进系统的初始结构图,直到得到符合要求的结构图为止。 5)修改和补充数据词典 6)制定测试计划。
在系统结构图中的模块 传入模块 ─ 从下属模块取得数据,经过某些处理,再将其传送给上级模块。它传送的数据流叫做逻辑输入数据流。 传出模块 ─ 从上级模块获得数据,进行某些处理,再将其传送给下属模块。它传送的数据流叫做逻辑输出数据流。 变换模块 ─ 它从上级模块取得数据,进行特定的处理,转换成其它形式,再传送回上级模块。它加工的数据流叫做变换数据流。 协调模块 ─ 对所有下属模块进行协调和管理的模块。
变换型系统结构图 变换型数据处理问题的工作过程大致分为三步,即取得数据,变换数据和给出数据。 相应于取得数据、变换数据、给出数据,变换型系统结构图由输入、中心变换和输出等三部分组成。
事务型系统结构图 它接受一项事务,根据事务处理的特点和性质,选择分派一个适当的处理单元,然后给出结果。 在事务型系统结构图中,事务中心模块按所接受的事务的类型,选择某一事务处理模块执行。各事务处理模块并列。每个事务处理模块可能要调用若干个操作模块,而操作模块又可能调用若干个细节模块。
变换分析 变换分析方法由以下四步组成: 1) 重画数据流图; 2) 区分有效(逻辑)输入、有效(逻辑)输出和中心变换部分; 3) 进行一级分解,设计上层模块; 4) 进行二级分解,设计输入、输出和中心变换部分的中、下层模块。
(1)在DFD 图上标出逻辑输入、逻辑输出和变换中心的分界 c,e 逻 辑输入 w,u 逻 辑输出 变换中心 A e B a C b D c E d P Q R w u v r p -------- 具有变换型数据流图
第一级分解后的 SC 图(含协调、传入、变换、传出模块) (2) 完成第一级分解 变换中心 A a b c P w u v r p B C D d e E Q R W U V Mc 顶 层 U,w C,e C,e U,w MA MT ME 第一层 第一级分解后的 SC 图(含协调、传入、变换、传出模块)
变换中心 Mc MA1 ME1 MA2 Q P R ME2 r w 第一级分解后的 SC 图(另一种画法) A a b c P w u v D d e E Q R W U V Mc MA1 ME1 C e U MA2 Q P R ME2 c,p p r w,u w 第一级分解后的 SC 图(另一种画法)
(3) 完成第二级分解 变换中心 MA MT ME C E W U B D Q P R V A 对逻辑输入的分解 对变换中心加工的分解 U,w e W U b d C,p r r p B D v Q P R V a A 对逻辑输入的分解 对变换中心加工的分解 对输出的分解
(4) 获得完整的 SC 图 MA C B A E D MT Q P R ME W U V MC 从变换分析导出的初始 SC 图 c, e
① 在选择模块设计的次序时,必须对一个模块的全部直接下属模块都设计完成之后,才能转向另一个模块的下层模块的设计。 运用变换分析方法建立系统的SC时需注意以下几点: ① 在选择模块设计的次序时,必须对一个模块的全部直接下属模块都设计完成之后,才能转向另一个模块的下层模块的设计。 ② 在设计下层模块时,应考虑模块的耦合和内聚问题,以提高初始结构图的质量。
运用变换分析方法建立系统的SC时需注意以下几点: ③ 使用“黑箱”技术: 在设计当前模块时,先把这个模块的所有下层模块定义成“黑箱”,在设计中利用它们时,暂时不考虑其内部结构和实现。在这一步定义好的“黑箱”,在下一步就可以对它们进行设计和加工。这样,又会导致更多的“黑箱”。最后,全部“黑箱”的内容和结构应完全被确定。 ④ 在模块划分时,一个模块的直接下属模块一般在5个左右。如果直接下属模块超过10个,可设立中间层次。 ⑤ 如果出现了以下情况,就停止模块的功能分解: 当模块不能再细分为明显的子任务时; 当分解成用户提供的模块或程序库的子程序时; 当模块的界面是输入/输出设备传送的信息时; 当模块不宜再分解得过小时。
---- 是将具有事务型的DFD图导出SC图 事务分析 ---- 是将具有事务型的DFD图导出SC图 事务源 I A L M N O B C D E F G H 事务中心
I A L M N O B C D E F G H 主模块 B C D H A G F E 取得A L M N 给出H
变换分析是软件系统结构设计的主要方法。 一般,一个大型的软件系统是变换型结构和事务型结构的混合结构。所以,我们通常利用以变换分析为主,事务分析为辅的方式进行软件结构设计。
设计的后处理 为每一个模块写一份处理说明 为每一个模块提供一份接口说明 确定全局数据结构和局部数据结构 指出所有的设计约束和限制 进行概要设计的评审 进行设计的优化(如果需要和可能的话)
设计实例: 教材P96 – P102
作业: 题3、4;