740 likes | 905 Views
软件生命周期. 软件生存周期. 可行性研究. 软件定义. 需求分析. 概要设计. 详细设计. 软件开发. 实 现. 集成测试. 确认测试. 软件使用与维护. 使用与维护. 退役. 软件设计 是后续开发步骤及软件维护工作的基础。如果没有设计,只能建立一个不稳定的系统结构. 第五章 软件设计. 主要内容: ▲ 软件设计的目标和任务 ▲ 软件设计基础 ▲ 模块的独立性 ▲ 结构化设计方法 ▲ 数据设计及文件设计 ▲ 过程设计. 讨论要点. (1) 如何将分析模型转换为软件 设计? (2) 作为软件工程师在软件设计
E N D
软件生命周期 软件生存周期 可行性研究 软件定义 需求分析 概要设计 详细设计 软件开发 实 现 集成测试 确认测试 软件使用与维护 使用与维护 退役
软件设计是后续开发步骤及软件维护工作的基础。如果没有设计,只能建立一个不稳定的系统结构软件设计是后续开发步骤及软件维护工作的基础。如果没有设计,只能建立一个不稳定的系统结构
第五章 软件设计 主要内容: ▲ 软件设计的目标和任务 ▲ 软件设计基础 ▲ 模块的独立性 ▲ 结构化设计方法 ▲ 数据设计及文件设计 ▲ 过程设计
讨论要点 (1)如何将分析模型转换为软件 设计? (2)作为软件工程师在软件设计 方面应使用哪些基本原则和 概念?
引言: 软件设计的目标和目的 软件需求:解决“做什么” 软件设计:解决“怎么做” 1. 软件设计的任务 问题结构(软件需求) 软件结构 从软件需求规格说明书出发,形成软件的具体设计方案。 映射
将分析模型转换为软件设计 加 数 工 据 过程设计 E-R图 数据 流图 规 对 数据 字典 约 象 接口设计 描 述 体系结构设计 状态变迁图 控制规约 数 据 设 计 分析模型 设计模型
2.软件的总体结构主要回答的问题 • 软件的组成部分 • 软件的层次关系 • 模块的内部处理逻辑 • 模块之间的界面
3. 软件设计的问题 • 工具 —如何描述软件的总体结构 • 方法 —用什么方法有问题结构导出 软件结构 • 评估准则 —什么样的软件结构是 “最优的”
4. 软件设计方法 • 结构化设计方法(SD) • 面向数据结构的设计方法(JSD方法) • 面向对象的设计方法(OOD)
5. 软件设计分为两个阶段: (1)概要设计(总体设计) 确定软件的结构以及各组成成分 (子系统或模块)之间的相互关系。 (2)详细设计 确定模块内部的算法和数据结构,产生描述各模块程序过程的详细文档。
软件设计任务 • 从工程管理的角度来看,软件设计分两步完成。 • 概要设计,将软件需求转化为数据结构和软件的系统结构。 • 详细设计,即过程设计。通过对结构表示进行细化,得到软件详细的数据结构和算法。
软 件 工 程 ---第4章 概要设计
§5.1设计过程 开始考虑“How”,但仍属高层设计(确定黑盒关系) 1、设想供选择的方案 2、选择合理的方案 3、确定最佳方案: 从DFD出发进行任务分解,不同的划分方法即对应不同的方案。每个合理的方案应配备下列4份资料: ⑴系统流程图 ⑵组成系统的物理元素清单 ⑶成本/效益分析 ⑷进度计划 • 选择最佳方案并制定详细的实现计划 4、功能分解
§1. 概要设计的过程 5、结构设计 —— 模块化思想: 将DFD细化,至每个子功能都明白易懂;每个模块完成一个子功能;每层模块合成一个高一级的功能。 6、数据库设计 7、测试计划 8、文档、审查
总体设计阶段的文档 (1)总体设计说明书(包括系统实现方案和软件模块结构); (2)测试计划(包括测试策略、测试方案、预测的测试结果、测试进度计划等); (3)用户手册(根据总体设计阶段的结果,编写的初步的用户操作手册); (4)详细的实现计划; (5)数据库设计结果。
软件总成本 最小成本区 接口成本 成本 成本 / 模块 模块数目 §5.2 软件设计原理 1、模块化原理: 经验1:E(P1+P2)>E(P1)+E(P2) 经验2:
模块化概念 • 模块:又称构件,是能够单独命名并独立地完成一定功能的程序语句的集合。例如高级语言中的过程、函数、子程序等都可作为模块 • 模块化是软件的一个重要属性。模块化的特性提供了人们处理复杂的问题的一种方法,同时也使得软件能够被有效地管理。
模块化(Modularity) 模块化是好的软件设计的一个基本准则 高层模块 从整体上把握 问题,隐蔽细节 复杂问题 较小问题 分解 可减小解题所需的总的工作 分解
(一个模块 直接调用 的模块数) 2. 软件结构度量术语 扇出 深 度 (模块的 层数) (调用一个给定模 块的模块个数) 扇入 宽度 (同一层最大模块数)
模块化和软件成本 软件总成本 成本或工作量 最小成本区域 集成成本 M 成本/模块 模块数量
§2. 软件设计原则 我们在考虑问题时,集中考虑和当前问题有关的方面,而忽略和当前问题无关的方面,这就是抽象。或者说抽象就是抽出事物的本质特性而暂时不考虑它们的细节。 软件工程过程的每一步,都是对软件解法的抽象层次的一次细化。在可行性研究阶段,软件被看作是一个完整的系统部分;在需求分析期间,我们使用在问题环境中熟悉的术语来描述软件的解法;当我们由总体设计阶段转入详细设计阶段时,抽象的程度进一步减少;最后,当源程序写出来时,也就达到了抽象的最低层。 例:开发一个CAD软件,实现一个二维绘图系统的全部功能,供低级计算机辅助设计使用。 2、抽象: 忽略细节,分层理解问题,自顶向下层层加细。
§2. 软件设计原则 3、信息隐蔽(Information hiding)与局部化 每一个模块的实现细节对于其他模块来说是隐蔽的,模块中所包括的信息不允许其他不需要这些信息的模块调用。 信息隐蔽对于软件的测试与维护都有很大的好处。因为对于软件的其它部分来说,绝大多数数据和过程都是隐蔽的,这样,在修改期间由于疏忽而引入的错误所造成的影响就可以局限在一个或几个模块内部,不至波及到软件的其他部分。 局部化就是将一些关系密切的软件元素物理地放得彼此靠近。
§2. 软件设计原则 4、模块独立性(Module independence) * 好设计的关键:每个模块完成一个相对独立的子功能,并且与其它模块间的接口简单。 模块独立性是模块化、抽象和信息隐蔽概念的直接结果。 独立性的度量:耦合(Coupling)&内聚(Cohesion)
Great deal of dependence Independent Highly coupled Loosely coupled Uncoupled §2. 软件设计原则 耦合表示一个软件结构内各个模块之间的互连程度,应尽量选用松散耦合的系统 ⑴ 耦合(Coupling)
…… A B A: ………… ………… goto C1 ………… ………… C D C: ………… ………… C1: …… …… §2. 软件设计原则 独立性由弱到强(耦合程度由强到弱)排列为: 内容耦合(Content Coupling): 一个模块直接影响另一个 例1:A访问C的内部数据或不通过正常入口而转入C的内部。
A: ……………… ……………… entry 1: ……………… ……………… entry 2: ……………… ……………… A B §2. 软件设计原则 例2:部分代码重叠(常出现在汇编程序中) 例3:一个模块有多个入口(功能) The least desirable
Global : V1 V2 Global : V1 V2 A: ………… ………… A1=V1+V2 ………… ………… B: ………… ………… V1=B1 ………… ………… A: ………… ………… V1++ ………… ………… B: ………… ………… V2=B1+V1 ………… ………… §2. 软件设计原则 公共耦合(Common coupling):几个模块共享一个数据区域 • 问题:公共部分的改动将影响所有调用它的模块; • 公共部分的数据存取无法控制; • 复杂程度随耦合模块的个数增加而增加。
B Fn …… Flag A F2 …… Flag F1 §2. 软件设计原则 接口单一,但仍然影响被控模块的内部逻辑。 控制耦合(Control coupling):一个模块通过传递控制信息来控制另一个模块 控制耦合:当把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素时,就出现了特征耦合.
数据耦合(Data coupling): 只有数据在模块之间进行交换 原则:尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,完全不用内容耦合。
from disk from tape from …… A: Read inputs ⑵ 内聚(Cohesion): 一个模块内各元素结合的紧密程度. Goal: as cohesive as possible. §2. 软件设计原则 低内聚: 偶然内聚(Coincidental cohesion) 模块中任务没有多大关系 逻辑内聚(Logical cohesion):相似功能放在一个模块 例如:
enter data check data manipulate data §2. 软件设计原则 时间内聚(Temporal cohesion):模块内的功能在同一时间段内完成 例如:系统的初始化 问题:不同功能混在一个模块中,有时共用部分编码,使局部功能的修改牵动全局。 中内聚: 过程内聚(Procedural cohesion):模块内的处理是相关的,而且必须以特定顺序执行 例如:
§2. 软件设计原则 通信内聚(Communicational cohesion):模块中所有元素都用同一个输入数据或产生同一个输出数据 例如:从同一磁带上读取不相干的数据 ——可能破坏独立性。 高内聚: 顺序内聚(Sequential cohesion):模块的多个功能使用相同的数据结构和入口 功能内聚(Functional cohesion):所有元素合力完成一个单一功能,缺一不可
§2. 软件设计原则 耦合、内聚与模块独立性的关系:
§2. 软件设计原则 §5. 3结构设计原则(启发原则)
§2. 软件设计原则 结构设计原则 • 提高模块独立性 • 争取低耦合、高内聚(增加内聚 > 减少耦合) 2. 模块规模适中: 过大不易理解;太小则接口开销过大。注意分解后不应降低模块的独立性。
§2. 软件设计原则 3. 选择适当的深度、宽度、扇出和扇入 深度 = 分层的层数。过大表示分工过细。 宽度 = 同一层上模块数的最大值。过大表示系统复杂度大。
A A的扇出 A的扇入 A §2. 软件设计原则 扇出 = 一个模块直接调用\控制的模块数。 3 fan-out 9 扇入 = 直接调用该模块的模块数 在不破坏独立性的前提下,fan-in大的比较好。
M A: ………… if …… then goto B1 ………… ………… A: ………… if …… then goto M1 ………… ………… B: ………… ………… B1: ………… ………… M: ………… ………… M1: goto C1 ………… ………… A C B 作用域在控制域内 作用域超出了控制域 §2. 软件设计原则 M的控制域为 {M,A,B,C} 4、作用域在控制域内 控制域 作用域:M中的一个判定所影响的模块。 例如: 上例中A的作用超出了控制域。改进方法之一,可以把A中的 if移到M中;方法之二,可以把C移到A下面。
§2. 软件设计原则 5、降低接口的复杂程度:接口复杂可能表明模块的独立性差。 6、单出单入,避免内容耦合。 7、模块功能可预测 —— 相同输入必产生相同输出。反例:模块中使用全局变量或静态变量,则可能导致不可预测。
5.4 描绘软件结构的图形工具5.4.1 层次图和HIPO图 层次图用来描绘软件的层次结构。在图5.2中已经非正式地使用了层次图。虽然层次图的形式和第3.7节中介绍的描绘数据结构的层次方框图相同,但是表现的内容却完全不同。层次图中的一个矩形框代表一个模块,方框间的连线表示调用关系而不像层次方框图那样表示组成关系。图5.3是层次图的一个例子。
层次图很适于在自顶向下设计软件的过程中使用。层次图很适于在自顶向下设计软件的过程中使用。 HIPO图是美国IBM公司发明的“层次图加输入/处理/输出图”的英文缩写。为了能使HIPO图具有可追踪性,在H图(层次图)里除了最顶层的方框之外,每个方框都加了编号。 和H图中每个方框相对应,应该有一张IPO图描绘这个方框代表的模块的处理过程。HIPO图中的每张IPO图内都应该明显地标出它所描绘的模块在H图中的编号,以便追踪了解这个模块在软件结构中的位置。
5.4.2 结构图 Yourdon提出的结构图是进行软件结构设计的另一个有力工具。结构图和层次图类似,也是描绘软件结构的图形工具,图中一个方框代表一个模块,框内注明模块的名字或主要功能;方框之间的箭头(或直线)表示模块的调用关系。因为按照惯例总是图中位于上方的方框代表的模块调用下方的模块,即使不用箭头也不会产生二义性,为了简单起见,可以只用直线而不用箭头表示模块间的调用关系。
在结构图中通常还用带注释的箭头表示模块调用过程中来回传递的信息。如果希望进一步标明传递的信息是数据还是控制信息,则可以利用注释箭头尾部的形状来区分:尾部是空心圆表示传递的是数据,实心圆表示传递的是控制信息。图5.5是结构图的一个例子。在结构图中通常还用带注释的箭头表示模块调用过程中来回传递的信息。如果希望进一步标明传递的信息是数据还是控制信息,则可以利用注释箭头尾部的形状来区分:尾部是空心圆表示传递的是数据,实心圆表示传递的是控制信息。图5.5是结构图的一个例子。 以上介绍的是结构图的基本符号,也就是最经常使用的符号。此外还有一些附加的符号,可以表示模块的选择调用或循环调用。图5.6表示当模块M中某个判定为真时调用模块A,为假时调用模块B。图5.7表示模块M循环调用模块A、B和C。
图5.5 结构图的例子——产生最佳解的一般结构
注意,层次图和结构图并不严格表示模块的调用次序。虽然多数人习惯于按调用次序从左到右画模块,但并没有这种规定,出于其他方面的考虑(例如为了减少交叉线),也完全可以不按这种次序画。此外,层次图和结构图并不指明什么时候调用下层模块。通常上层模块中除了调用下层模块的语句之外还有其他语句,究竟是先执行调用下层模块的语句还是先执行其他语句,在图中丝毫没有指明。事实上,层次图和结构图只表明一个模块调用那些模块,至于模块内还有没有其他成分则完全没有表示。注意,层次图和结构图并不严格表示模块的调用次序。虽然多数人习惯于按调用次序从左到右画模块,但并没有这种规定,出于其他方面的考虑(例如为了减少交叉线),也完全可以不按这种次序画。此外,层次图和结构图并不指明什么时候调用下层模块。通常上层模块中除了调用下层模块的语句之外还有其他语句,究竟是先执行调用下层模块的语句还是先执行其他语句,在图中丝毫没有指明。事实上,层次图和结构图只表明一个模块调用那些模块,至于模块内还有没有其他成分则完全没有表示。
通常用层次图作为描绘软件结构的文档。结构图作为文档并不很合适,因为图上包含的信息太多有时反而降低了清晰程度。但是,利用IPO图或数据字典中的信息得到模块调用时传递的信息,从而由层次图导出结构图的过程,却可以作为检查设计正确性和评价模块独立性的好方法。传送的每个数据元素都是完成模块功能所必须的吗?反之,完成模块功能必须的每个数据元素都传送来了吗?所有数据元素都只和单一的功能有关吗?如果发现结构图上模块间的联系不容易解释,则应该考虑是否设计上有问题。通常用层次图作为描绘软件结构的文档。结构图作为文档并不很合适,因为图上包含的信息太多有时反而降低了清晰程度。但是,利用IPO图或数据字典中的信息得到模块调用时传递的信息,从而由层次图导出结构图的过程,却可以作为检查设计正确性和评价模块独立性的好方法。传送的每个数据元素都是完成模块功能所必须的吗?反之,完成模块功能必须的每个数据元素都传送来了吗?所有数据元素都只和单一的功能有关吗?如果发现结构图上模块间的联系不容易解释,则应该考虑是否设计上有问题。