询价QQ:15208189    咨询热线:13520752365

联系我们 /contact

letou国际米兰|网站

电 话:13520752365

传 真:010-58043628

Q Q:15208189

邮 箱:15208189@qq.com

联 系 人:苏朋朋

letou国际米兰:北京市房山区辰光东路16号院4号楼9层904

模块,光栅系列 您现在的位置:letou国际米兰 > letou国际米兰 > 模块,光栅系列 >

letou国际米兰模块结构图_图

发布:admin   浏览:


  第7章 结构化系统设计 章 本章主要内容 ? 系统设计的任务 ? 总体设计 – 结构化设计的概念、基本原则 结构化设计的概念、 – 从数据流图导出结构图 ? 详细设计 – – – – – – 代码设计 输出设计 输入设计 人机对话设计 模块详细设计 数据库设计、 数据库设计、网络设计 ? 系统设计说明书 7.2.1 模块的概念 ? 模块 模块(Module)一词使用很广泛。通常对应于 一词使用很广泛。 一词使用很广泛 用一个名字就可以调用的一段程序语句( 用一个名字就可以调用的一段程序语句(子 程序或函数) 程序或函数) ? 模块具有输入和输出、逻辑功能、运行程序、 模块具有输入和输出、逻辑功能、运行程序、 内部数据四种属性。 内部数据四种属性。 计算年龄 模块的图形表示方法 int computeAge(date birthday) 模块的函数接口表示 7.2.2 模块结构图 ? 结构图 结构图(Structured Chart)描述系统的模块结 描述系统的模块结 构及模块间的联系 ? 结构图中的主要成分有: 结构图中的主要成分有: – 模块:用长方形表示 模块: – 调用:从一个模块指向另一模块的箭头表示前一 调用: 个模块调用后一个模块。 个模块调用后一个模块。有循环调用和条件调用 – 数据:用带圆圈的小箭头表示从一个模块传递给 数据: 另一模块的数据(有实义) 另一模块的数据(有实义) – 控制信息:带涂黑圆圈的小箭头表示一个模块传 控制信息: 送给另一模块的控制信息 结构图的画法 主调模块 主调模块 被调模块 被调模块 被调模块 被调模块 条件调用 循环调用 结构图无严格的模块调用顺序, 1、结构图无严格的模块调用顺序,但一般习惯从左至右 因为约定遵从从上向下的调用, 2、因为约定遵从从上向下的调用,调用关系也可以不使 用箭头,而直接使用直线 用箭头, 模块间传递的信息如果出现在数据字典中, 3、模块间传递的信息如果出现在数据字典中,则视为数 据,否则为控制信息 一个完整的结构图 有效数据 EOF 有效数据 计算 EOF 结果 结果 获得有效数据 编辑数据 EOF 编辑数据 有效数据 生成报表 日期 打印报表 行 行 获得编辑数据 数据 EOF 数据 核对数据 编辑数据 打印表头 行 打印表尾 总 计 读入数据 编辑数据 显示无效 数据 打印一行 简单的模块结构图 ? 凭证管理模块的下层模块: 凭证管理模块的下层模块: – 凭证输入、凭证审核、凭证查询打印、凭证汇 凭证输入、凭证审核、凭证查询打印、 总、记账 模块设计的度量标准 ? 为了衡量模块的相对独立性,提出了模块间 为了衡量模块的相对独立性, 的耦合(Coupling)与模块的内聚 与模块的内聚(Cohesion) 的耦合 与模块的内聚 两个标准 – 耦合:模块和模块之间的联系程度 耦合: – 内聚:模块内部各元素之间的联系程度 内聚: ? 设计目标: 设计目标: – 模块内的联系越紧越好 – 模块间的联系越少越好 – 为什么? 为什么? 7.2.3 模块的耦合 double CalculateAvg() { int n; double total, average, value; scanf(“输入个数:\n”, 输入个数: 输入个数 total = sum(n); average=total/n; return(average); } 两个模块之间存在联系 影响耦合度的因素 ? 如果使用模块 需要了解模块B,那么 和B是 如果使用模块A需要了解模块 ,那么A和 是 需要了解模块 耦合的。 耦合的。影响模块间耦合程度有三方面的因 素: – 联系方式--模块间通过什么方式联系 联系方式-- --模块间通过什么方式联系 – 来往信息的作用--模块间来往信息作什么用 来往信息的作用-- --模块间来往信息作什么用 – 数量--模块间来往信息的多少。 数量--模块间来往信息的多少。 --模块间来往信息的多少 作用 混合 控制 数据 离坐标原点越远, 离坐标原点越远, 耦合程度越高 直接引用 0 少 数量 多 用过程 语句调用 方式 模块联系方式 ? 直接引用:一个模块直接存取另一个模块的 直接引用: 某些信息,例如全程变量、 某些信息,例如全程变量、FORTRAN的 的 common量、C语言的 语言的extern量、共享的通 量、C语言的 量 也称为公共环境耦合(common 信区等 。也称为公共环境耦合 environment coupling) – 降低这种耦合程度的办法是使数据局部化,即使 降低这种耦合程度的办法是使数据局部化, 用局部变量 ? 过程语句调用:一个模块调用另一个模块, 过程语句调用:一个模块调用另一个模块, 所有数据来往都以参数或返回值方式传递并 使用 来往信息的作用 ? 模块间的来往信息可以作数据用,也可以作 模块间的来往信息可以作数据用, 控制信息用 A 平均/ 平均/最高 B 取平均成绩 或最高成绩 取平均成绩 取最高成绩 平均成绩 A 最高成绩 成绩 (a)控制耦合 (a)控制耦合 (b)数据耦合 (b)数据耦合 来往信息的数量 ? 模块间传递的信息量越大,它们之间的耦合 模块间传递的信息量越大, 程度越高。 程度越高。 ? 一个模块最好只了解它确实需要使用的数据, 一个模块最好只了解它确实需要使用的数据, 而完全不知道其他数据的存在(独立性好) 而完全不知道其他数据的存在(独立性好) 耦合的类型 ? 根据以上因素,对耦合分类如下: 根据以上因素,对耦合分类如下: – – 数据耦合:采用子程序调用, 数据耦合:采用子程序调用,调用模块将需要进行处理 的数据传递给被调模块。数据耦合是不可避免的。 的数据传递给被调模块。数据耦合是不可避免的。 标记耦合: 标记耦合:如果调用模块将整个数据记录传递给被调模 而被调模块只使用了部分数据项, 块,而被调模块只使用了部分数据项,则称为标记耦合 或特征耦合。 或特征耦合。 控制耦合:一个模块将控制信息传递给另一个模块, 控制耦合:一个模块将控制信息传递给另一个模块,以 控制被调模块的内部处理逻辑。(可以分解) 。(可以分解 控制被调模块的内部处理逻辑。(可以分解) 公共环境耦合:如果两个模块共享同一全局数据, 公共环境耦合:如果两个模块共享同一全局数据,称为 公共耦合。 公共耦合。 内容耦合:两个模块之间的内部属性有直接关联, 内容耦合:两个模块之间的内部属性有直接关联,也称 病态耦合。(某些GOTO语句) 。(某些 语句) 病态耦合。(某些 语句 – – – 减低耦合的设计原则 结构化设计要求模块间的耦合程度尽可能小。 结构化设计要求模块间的耦合程度尽可能小。 ? 为此应: 为此应: – 用过程语句调用其它模块 – 模块间的参数作数据用 – 模块间的参数尽可能少 7.2.4 模块的内聚 double CalculateAvg() { int n; double total, average, value; scanf(“input value:”, while value=0.0 { n=n+1; total=total+value; scanf(“\ninput value:”, } average=total/n; return(average); } 模块内部各元素(变量、语句) 模块内部各元素(变量、语句)之间存在联系 内聚的好处 ? 模块的内聚反映模块内部联系的紧密程度。 模块的内聚反映模块内部联系的紧密程度。 ? 一个模块只需要做好一件事情,letou国际米兰,不要过分关 一个模块只需要做好一件事情, 心其它任务。 心其它任务。 ? 高内聚性的好处是可以提高程序的可靠性。 高内聚性的好处是可以提高程序的可靠性。 – 有一个调查表明,50%的强内聚性子程序是没有 有一个调查表明, % 错误的, 错误的,而只有 18%的弱内聚性子程序才是无错 % 的,弱内聚性子程序的出错机会要比强内聚性出 错机会高 6 倍,而修正成本则要高 19 倍。摘自 代码大全》 《代码大全》 内聚的类型 ? 模块的内聚可以分以下七类: 模块的内聚可以分以下七类: 偶然内聚(coincidental cohesion) 1、偶然内聚 逻辑内聚(Logical cohesion) 2、逻辑内聚 时间内聚(temporal cohesion) 3、时间内聚 步骤内聚(procedural cohesion) 4、步骤内聚 通信内聚(communicational cohesion) 5、通信内聚 顺序内聚(Sequential cohesion) 6、顺序内聚 7、功能内聚(functional_cohesion) 功能内聚 1、偶然内聚 、 当同一个子程序中的操作之间无任何联系时, 当同一个子程序中的操作之间无任何联系时, 为偶然内聚性,也叫作“无内聚性” 为偶然内聚性,也叫作“无内聚性”。 比如只是为了将程序中某几处凑巧相同的一些语 句组合起来形成的一个模块: 句组合起来形成的一个模块: P Q R S T B=A; read(Cardfile); D=C; 2、逻辑内聚 、 将几个逻辑上相似的功能放在一个模块中 准备 Y 取平均成绩? 取平均成绩 N 算平均成绩 算最高成绩 返 回 比如常见的出错处理模块,工作模块发现错误后, 比如常见的出错处理模块,工作模块发现错误后,调用 错误处理模块,将错误号作为控制参数传入, 错误处理模块,将错误号作为控制参数传入,然后出错 处理模块根据不同的错误号执行相应的操作 3、时间内聚 、 ? 将在有限时间单元内处理的成分组合为同 一模块 比如在程序初始化时所作的处理: 比如在程序初始化时所作的处理:tact txtAddr = psPerson.Addr txtMedirecno.Enabled = False ? 可视化程序设计中在窗口打开时初始化窗口中得控件内容, 可视化程序设计中在窗口打开时初始化窗口中得控件内容, 始化窗口中得控件内容 如列表框的项目、 如列表框的项目、文本框或单选钮的缺省取值 ? 还比如:C++的构造函数、析构函数 还比如: 的构造函数、 的构造函数 4、步骤内聚 、 ? 当子程序中的操作是按某一特定过程结构进 就是步骤内聚。 行的,就是步骤内聚。 ? 例如:用户想按一定的顺序打印告,子程序设计 例如:用户想按一定的顺序打印告, 成是用于按顺序打印销售收入、开支、 成是用于按顺序打印销售收入、开支、雇员电话 表的。 表的。 ? 步骤内聚在时间内聚的基础上增加了次序的 约束 模块划分示例 绘制划分后的模块图 STMRO (主模块) 主模块) 准备好的矩阵指示标记 准备好的矩阵指示标记 PREP PLANLOOP 部分结果、标签 部分结果、 等 TYPDECID 矩阵指示标记 ? 模块PERP是一个初始化模块,属时间内聚。 模块PERP是一个初始化模块,属时间内聚。 PERP是一个初始化模块 ? 模块PLANLOOP和TYPDECID都属于步骤内聚。前者的元素 都属于步骤内聚。 模块PLANLOOP和TYPDECID都属于步骤内聚 PLANLOOP 用于控制主循环, 用于控制主循环,后者的元素负责主循环的整个判定执 行过程 5、通信内聚 、 当模块内的成分引用共同的数据, 当模块内的成分引用共同的数据 ,而不存在 其他联系时, 其他联系时,称为通信内聚 库存 购货单 修改库存 期末不及格统计 学籍表 留退名单 开发货单 累计不及格统计 A、销售模块 B 、产生留退名单模块 6、顺序内聚 、 模块中某个成分的输出是另一成分的输入。 模块中某个成分的输出是另一成分的输入。 比如显示期末成绩通知: 比如显示期末成绩通知: 读 入 学 号 读 取 成 绩 级 判 断 留 退 取 不 及 格 科 目 取 科 目 补 考 安 排 显 示 数 据 6、顺序内聚 、 ? 顺序内聚有较强的内聚性 ? 是步骤内聚和通信内聚的结合 ? 例如:一个模块用于计算高于平均分的人数,步 例如:一个模块用于计算高于平均分的人数, 骤是先循环累计总分,然后计算得到平均分, 骤是先循环累计总分,然后计算得到平均分,最 后循环统计高于平均分的人数 ? 有步骤的先后,而且前一个步骤的结果要用于后 有步骤的先后, 一步骤的运算中 ? 但仍然不是最高的内聚类型 7、功能内聚 、 ? 一个模块包括并且仅仅包括为完成一个具体 任务所需要的所有成分,称为功能内聚。 任务所需要的所有成分,称为功能内聚。 ? 功能内聚性是最强也是最好的一种内聚 – 例如:打印职工名单,PrintStaffList() 例如:打印职工名单, – 例如:计算平均分,CalculateAvg() 例如:计算平均分, ? 仅用一个动宾词组能明确指出这个模块的所 有功能。 有功能。 内聚的评分 ? 耦合和内聚的概念是 耦合和内聚的概念是Stevens等人提出的, 等人提出的, 等人提出的 是测量一个模块化系统好坏的标志。 是测量一个模块化系统好坏的标志。 ? 按他们的观点, 给上述七种内聚评分如下: 按他们的观点, 给上述七种内聚评分如下: – 功能内聚10分 功能内聚10 10分 – 顺序内聚9分 顺序内聚9 – 通信内聚7分 通信内聚7 – 步骤内聚5分 步骤内聚5 – 时间内聚3分 时间内聚3 – 逻辑内聚1分 逻辑内聚1 – 偶然内聚0分 偶然内聚0 ? 可以给一个软件的所有模块打分,最后计算 可以给一个软件的所有模块打分, 平均分, 平均分,作为软件结构质量评价的参考 耦合和内聚的关系 ? 二者就像连体兄弟,存在紧密相关的关系: 二者就像连体兄弟,存在紧密相关的关系: – 模块内的高内聚往往意味着模块间的松耦合 – 反之,公司动态,低内聚一般会带来紧耦合 反之, 7.2.5 作用范围与控制范围 ? 一个判断的作用范围是所有这样的模块的集 一个判断的作用范围是所有这样的模块的集 合,这些模块内含有依赖于这个判断结果的 处理。或称影响范围。 处理。或称影响范围。 ? 一个模块的控制范围是指它本身及其所有下 一个模块的控制范围是指它本身及其所有下 属模块的集合。 属模块的集合。 模块A的控制范围是: 模块A的控制范围是: A 、 B 、 C、 D A 计算工资 假如判断x出现在模块A 假如判断x出现在模块A 并且仅在A 中,并且仅在A中使用 了x,则该判断的作用 范围是: 范围是:A, 而B、C、D不受影响 B 计算临时工工资 C 计算职工工资 D 计算总工资 判断的设计原则 ? 一个设计原则:对于任何一个判断,其作用 一个设计原则:对于任何一个判断, 范围应该是这个判断所在模块的控制范围的 一个子集 ? 该原则的目的:消除控制耦合,降低耦合度 该原则的目的:消除控制耦合, – 想象一下,假设某个控制标志在系统的很多部分 想象一下, 发挥作用,那么可能会产生这样一种情况: 发挥作用,那么可能会产生这样一种情况:错误 发作的位置离产生错误的源头很远, 发作的位置离产生错误的源头很远,这给程序调 试和维护带来极大困难。 试和维护带来极大困难。 作用范围和控制范围图示 TOP TOP X A Y X B Y A B B1 (a) TOP B2 B1 (b) B2 TOP Y X X B Y B A B1 (c) B2 A B1 (d) B2 期末成绩查询 主模块 Main() () { stuNo = 读入学号模块 调用成绩查询模块 调用成绩查询模块 调用显示模块 调用显示模块 } 子模块 成绩查询模块() 成绩查询模块() { 调用查期末成绩模块 调用查期末成绩模块 如果有不及格科目则 标志1=True 标志 调用不及格处理模块 调用不及格处理模块 } 不及格处理模块() 不及格处理模块() { 标志2=确定留退模块 确定留退模块() 标志 确定留退模块() 如果标志2 如果标志 != True 则 调用查补考安排模块 调用查补考安排模块 } 显示结果模块() 显示结果模块() { 调用显示成绩模块 调用显示成绩模块 如果标志1==True 则 如果标志 调用不及格显示模块 调用不及格显示模块 } 显示不及格处理模块() 显示不及格处理模块() { 如果标志2==True 则 如果标志 调用留退通知模块 调用留退通知模块 否则 调用补考通知模块 调用补考通知模块 } 改写后的模块图 学生期末成绩查询 读入学号 显示成绩 查询成绩 显示成绩 不及格处理 确定留退 显示补考 显示留退 7.2.6 模块的扇入与扇出 ? 模块的扇入是指有多少个上级模块调用它。 模块的扇入是指有多少个上级模块调用它 指有多少个上级模块调用它。 ? 模块的扇出是指模块的直属下层模块的个数, 模块的扇出是指模块的直属下层模块的个数, 指模块的直属下层模块的个数 扇出系数不宜过大 A B的扇出为1 的扇出为1 A的扇出为2 的扇出为2 B B1 C1 C C2 C的扇出为3 的扇出为3 C3 T的扇入为2 的扇入为2 T 总体设计原则 ? 设计功能内聚的模块 ? 模块使用过程语句调用其它模块,传递的参 模块使用过程语句调用其它模块, 数作数据用, 数作数据用,并且尽可能少 ? 模块内语句数一般为 模块内语句数一般为50-100 ? 平均扇出系数最好是 平均扇出系数最好是3-5 ? 高层模块高扇出,最低层模块高扇入 高层模块高扇出, ? 一个判断的作用范围是判断所在模块的控制 范围的子集 7.2.7 模块总体设计举例 问题描述:病人监护系统中的实时监测模块。 问题描述:病人监护系统中的实时监测模块。 – 该模块使用病床专用设备测量病人的若干生理参 如体温、脉搏、血压等等。 数,如体温、脉搏、血压等等。 – 每个病人各种指标的安全范围由医生预先指定。 每个病人各种指标的安全范围由医生预先指定。 – 每经过一定的时间间隔,监测模块从监视设备读 每经过一定的时间间隔, 入这些数据,并存入数据库中。 入这些数据,并存入数据库中。 – 若发现某个指标超出合理范围,则向维修站发出 若发现某个指标超出合理范围, 设备故障通知,报告床号。 设备故障通知,报告床号。 – 若发现某个指标越出安全范围,则向护理站发出 若发现某个指标越出安全范围, 通知,报告病人号。 通知,报告病人号。 分析产生的DFD 分析产生的 合理 数据 读取 数据 数据 检查 数据 存储 数据 不安 全因 素 病历 病人 维 修 站 不合理 数据 通报 不 安全 因素 护 理 站 可以划分哪些 模块呢? 模块呢? 初始结构图 病人监护 EOF,EF , PN,FS , EF PN,FS , USF, , EF PN—病人号;BN 床位号 SR—安 床位号; PN 病人号;BN—床位号;SR 安 病人号 全范围;FS—各指标数据 EF—设 各指标数据; 全范围;FS 各指标数据; EF 设 备故障标志; EOF——标志已查过 备故障标志; EOF 标志已查过 最后一个病人; FS2—标志指标是 最后一个病人; FS2 标志指标是 否合理; USF—标志指标不安全 否合理; USF 标志指标不安全 EF,USF , PN,FS , 采集数据 EOF PN,BN BN FS EF FS 检查数据 FS PN SR FS2 EF PN,FS , USF ,EF 处理数据 PN, , EF PN,FS , 获 取 下 一 个 病 人 读 取 数 据 检 查 不 合 理 范 围 查 询 安 全 范 围 判 定 病 人 是 否 安 全 写 数 据 库 通 报 设 备 故 障 通 报 不 安 全 因 素 第1次改进 次改进 ? “处理数据”模块没有实质性的功能,所包含 处理数据”模块没有实质性的功能, 处理数据 的三个子模块相互之间没有什么关联, 的三个子模块相互之间没有什么关联,内聚 程度很低。 程度很低。 ? 该模块只是充当了“管道”,改进如下: 该模块只是充当了“管道” 改进如下: – 废除“处理数据”模块; 废除“处理数据”模块; – 直接由主模块调用“通报设备故障”、“通报不 直接由主模块调用“通报设备故障” 安全因素” 写数据库” 安全因素”和“写数据库”三个模块 第1次改进结果 次改进结果 病人监护 采集数据 检查数据 通报 设备故障 通报不安 全因素 写数据库 第2次改进 次改进 ? 通报设备故障时应通报床位号而不应是病人 因此要传递床位号。 号,因此要传递床位号。 ? 床位号 可由“采集数据”模块传给主模块, 床位号BN可由“采集数据”模块传给主模块, 可由 再由主模块传递给“通知设备故障”模块。 再由主模块传递给“通知设备故障”模块。 但这样做增加了模块间的联系,改为由“ 但这样做增加了模块间的联系,改为由“采 集数据” 集数据”模块直接调用 第2次改进结果 次改进结果 病人监护 PN, PN,FS EOF, EOF,EF EF PN,FS PN, USF PN, PN, FS 通报 不安全因素 PN, PN,FS 写数据库 采集数据 EOF PN, PN,BN 检查数据 FS PN FS SR BN EF USF 获取 下一个病人 FS 读取数据 PN, PN,EF SR EF 查询安全 判定病人是 否安全 范围 FS2 检查 不合理范围 通报 设备故障 第3次改进 次改进 ? 若由“检查数据”模块直接调用“通报不安 若由“检查数据”模块直接调用“ 全因素”模块,则可减少模块间的联系, 全因素”模块,则可减少模块间的联系,即 不用传递USF标志(排除控制耦合)。 标志( 不用传递 标志 排除控制耦合)。 ? 这样的话,“检查数据”的名字改为“报告 这样的话, 检查数据”的名字改为“ 不安全因素” 不安全因素”更为恰当 第3次改进结果 次改进结果 病人监护 PN, PN,FS EOF, EOF,EF PN, PN, FS EF 采集数据 PN 报告不安全因素 EF USF SR, SR,FS 写数据库 PN, PN,FS 查询安全范围 判定病人是否安全 通报不安全因素 第4次改进 次改进 ? “获取下一个病人”模块要返回病人号和床位 获取下一个病人” 获取下一个病人 接口比较复杂。如果使“ 读取数据” 号,接口比较复杂。如果使“ 读取数据”模 块包括从病人号查床位号的功能, 块包括从病人号查床位号的功能,则“获取 下一个病人”模块的接口可以简化 下一个病人” 第4次改进结果 次改进结果 采集数据 EOF FS PN EF PN 获取 下一个病人 读取数据 PN BN FS FS2 BN 从PN 查BN 检查 不合理因素 通报 设备故障 第5次改进 次改进 ? 通过床号读取数据,功能很明确,但目前包 通过床号读取数据,功能很明确, 含在“读取数据”模块中, 含在“读取数据”模块中,这部分程序代码 如果抽取出来单独成为一个模块更好, 如果抽取出来单独成为一个模块更好,名字 为“从床号读数据” 从床号读数据” ? 该模块可以成为一个公用模块,很易于重用 该模块可以成为一个公用模块, 第5次改进结果 次改进结果 采集数据 EOF PN PN EOF 获取下一个病人 PN 采集病人数据 FS BN BN EF 从PN查BN PN查 FS 从床号读数据 BN FS2 检查不合理因素 通报设备故障 第6次改进 次改进 ? “ 从床号读数据”应该是功能单一,调用“通 从床号读数据”应该是功能单一,调用“ 报设备故障”不应属于该模块内容。 报设备故障”不应属于该模块内容。 ? 将“通报设备故障”改为上层模块调用,使 通报设备故障”改为上层模块调用, 从床号读数据”模块功能更明确, “从床号读数据”模块功能更明确,公用性 也更好 第6次改进结果 次改进结果 PN, PN,FS EOF, EOF,EF PN, PN,FS 病人监护 EF EF FS 采集数据 EOF FS 报告不安全因素 EF PN SR 写数据库 PN,FS PN 判定 下一个病人 PN PN EF FS,SR USF 采集 病人数据 BN EF FS 检查 安全范围 BN 判定病人是 否安全 通报 不安全因素 BN PN查 从PN查BN FS 从床号 读数据 FS2 通报 设备故障 检查不合理因素 第7次改进 次改进 ? 给护士站或维修站的通报消息可能采用了同 给护士站或维修站的通报消息可能采用了同 一种方式或界面,因此可能会有公用的模块, 一种方式或界面,因此可能会有公用的模块, 比如“写一行” 或者“发出警报”之类) 比如“写一行”(或者“发出警报”之类) ? 因此再抽出一个模块“写一行”,供两个模 因此再抽出一个模块“写一行” 块调用。 块调用。 第7次改进结果 次改进结果 病人监护 EOF, EOF,EF 采集数据 EOF PN 判定 下一个病人 PN 从PN查BN PN查 FS EF PN 采集 病人数据 EF BN EF FS BN BN 从床号 读数据 FS FS2 PN PN,FS PN, PN, PN,FS EF 报告不安全因素 EF USF SR FS,SR 判定病人是 检查安 否安全 全范围 一行 通报 设备故障 一行 写一行 EF FS 写数据库 PN,FS 通报 不安全因素 一行 FS 产生一行 检查不合理因素 结构图优化方法 ? 减少模块间的联系,减少参数传递,特别是 减少模块间的联系,减少参数传递, 控制信息的传递 ? 消除重复功能 ? 消除“管道”模块 消除“管道” ? 考虑变化 ? 控制模块大小 ? 整体考虑 ? 参照系统分析说明书 7.2.8 对已有程序进行重构 ? 重构(Refactoring):在不改变程序代码功 重构( ):在不改变程序代码功 ): 能的前提下, 能的前提下,对程序结构所进行的改造 ? 因为不是总能提前做出最好的设计,或者对 因为不是总能提前做出最好的设计, 遗留系统的维护过程中提高品质而做出的结 构变化 ? 参见《重构——改善既有代码的设计》 参见《重构 改善既有代码的设计》 改善既有代码的设计 模块重构例1 模块重构例 Void printOwing() { Enumeration e = _orders.elements(); double outstanding = 0.0 System.out.println(“************************”); System.out.println(“*****Customer Owes******”); System.out.println(“************************”); While (e.hasMoreElements()) { Order each = (Order) e.nextElement(); outstanding += each.getAmount(); } System.out.println(“name:” + _name) System.out.println(“amoutn:” + outstanding); } 重构后的例1 重构后的例 void printOwing() { Enumeration e = _orders.elements(); double outstanding = 0.0 printBanner(); while (e.hasMoreElements()) { Order each = (Order) 或者: 或者: e.nextElement(); void printOwing() { outstanding += each.getAmount(); printBanner(); } double outstanding = getOutstanding(); printDetails(outstanding); printDetails(outstanding); } } 模块重构例2 模块重构例 void setValue(String name, int value) { if (name.equals(“height”)) { _height = value; return; } if (name.equals(“width)) { _width = value; return; } } 为长方形的长和宽设置新值, 为长方形的长和宽设置新值,是一个逻辑内聚的例子 重构后的例2 重构后的例 void setHeight(int value) { _height = value; } void setWidth(int value) { _width = value; } 模块重构例3 模块重构例 获取某个数并且修改它以作其他用途,比如: 获取某个数并且修改它以作其他用途,比如: void getTotalOutstandingAndSetReadyForSummaries() 这是一个顺序内聚的模块,重构后: 这是一个顺序内聚的模块,重构后: double getTatalOutstanding() void setReadyForSummaries(double x) 模块设计案例(图书馆) 模块设计案例(图书馆) 学生设计: 学生设计: ? 图书馆有多种书,每种书有一个图书编号, 图书馆有多种书,每种书有一个图书编号, 在架数量随着每次读者借阅而减少 ? 当图书在架数量为 时,修改图书状态为“全 当图书在架数量为0时 修改图书状态为“ 部借出” 否则为“可借” 部借出”,否则为“可借” ? 每个读者仅允许借 本 每个读者仅允许借5本 ? 借阅记录需要保存图书编号、读者编号和借 借阅记录需要保存图书编号、 出日期 ? 还书时删除原来的借阅记录