1、内聚的模块,有能力 通过修改设计提高模块的内聚程度降低模块间的耦合程度通过修改设计提高模块的内聚程度降低模块间的耦合程度 ,从而获得较高的模块独立性。,从而获得较高的模块独立性。 31 5.3 启发规则 1. 1. 改进软件结构提高模块独立性改进软件结构提高模块独立性 2. 2. 模块规模应该适中模块规模应该适中 3. 3. 深度、宽度、扇出和扇入都应适当深度、宽度、扇出和扇入都应适当 4. 4. 模块的作用域应该在控制域之内模块的作用域应该在控制域之内 5. 5. 力争降低模块接口的复杂程度力争降低模块接口的复杂程度 6. 6. 设计单入口单出口的模块设计单入口单出口的模块 7. 7. 模块
2、功能应该可以预测模块功能应该可以预测 32 设计出软件的初步结构以后,应该审查分 设计出软件的初步结构以后,应该审查分 析这个结构,通过析这个结构,通过模块分解或合并,力求降低模块分解或合并,力求降低 耦合提高内聚耦合提高内聚。例如,多个模块公有的一个子。例如,多个模块公有的一个子 功能可以独立成一个模块,由这些模块调用;功能可以独立成一个模块,由这些模块调用; 有时可以通过分解或合并模块以减少控制信息有时可以通过分解或合并模块以减少控制信息 的传递及对全程数据的引用,并且降低接口的的传递及对全程数据的引用,并且降低接口的 复杂程度。复杂程度。 1. 改进软件结构提高模块独立性 33 经验表明
3、,一个模块的规模不应过大,最好能写在一页纸内经验表明,一个模块的规模不应过大,最好能写在一页纸内( (通通 常不超过常不超过6060行语句行语句) )。有人从心理学角度研究得知,当一个模块。有人从心理学角度研究得知,当一个模块 包含的语句数超过包含的语句数超过3030以后,模块的可理解程度迅速下降。以后,模块的可理解程度迅速下降。 过大的模块往往是由于分解不充分,但是进一步分解必须符合问过大的模块往往是由于分解不充分,但是进一步分解必须符合问 题结构,一般说来,分解后不应该降低模块独立性。题结构,一般说来,分解后不应该降低模块独立性。 过小的模块开销大于有效操作,而且模块数目过多将使系统接口过
4、小的模块开销大于有效操作,而且模块数目过多将使系统接口 复杂。因此过小的模块有时不值得单独存在,特别是只有一个模复杂。因此过小的模块有时不值得单独存在,特别是只有一个模 块调用它时,通常可以把它合并到上级模块中去而不必单独存在块调用它时,通常可以把它合并到上级模块中去而不必单独存在 。 2. 模块规模应该适中 模块过大:可理解程度下降模块过大:可理解程度下降 模块过小:开销大于有效操作、接口复杂模块过小:开销大于有效操作、接口复杂 34 深度深度表示软件结构中控制的层数。表示软件结构中控制的层数。 宽度宽度是软件结构内同一个层次上的模块总数的最大是软件结构内同一个层次上的模块总数的最大 值。值
5、。 扇出扇出是一个模块直接控制是一个模块直接控制( (调用调用) )的模块数目。的模块数目。扇出扇出 太大,应增加中间层次的控制模块;扇出小时,把太大,应增加中间层次的控制模块;扇出小时,把 下级模块进一步分解成若干个子功能模块或合并到下级模块进一步分解成若干个子功能模块或合并到 它的上级模块中去。它的上级模块中去。 扇入扇入是表明有多少个上级模块直接调用它。是表明有多少个上级模块直接调用它。 3. 深度、宽度、扇出和扇入都应适当 设计得很好的软件结构通常顶层扇出比较高,中层扇出较设计得很好的软件结构通常顶层扇出比较高,中层扇出较 少,底层扇入到公共的实用模块中去少,底层扇入到公共的实用模块中
6、去( (底层模块有高扇入底层模块有高扇入) ) 。 35 (1)(1)深度和程序长度之间应该有粗略的对应关系,当深度和程序长度之间应该有粗略的对应关系,当 然这个对应关系是在一定范围内变化的。如果层数然这个对应关系是在一定范围内变化的。如果层数 过多则应该考虑是否有许多管理模块过分简单了,过多则应该考虑是否有许多管理模块过分简单了, 能否适当合并。能否适当合并。 (2)(2)一般说来,宽度越大系统越复杂。对宽度影响最一般说来,宽度越大系统越复杂。对宽度影响最 大的因素是模块的扇出。大的因素是模块的扇出。 (3) (3) 一个设计得好的典型系统的平均扇出通常是一个设计得好的典型系统的平均扇出通常
7、是3 3或或 4(4(扇出的上限通常是扇出的上限通常是5 59)9)。 (4)(4)扇入越大则共享该模块的上级模块数目越多,这扇入越大则共享该模块的上级模块数目越多,这 是有好处的,但是,不能违背模块独立原理单纯追是有好处的,但是,不能违背模块独立原理单纯追 求高扇入。求高扇入。 36 高扇出的模块结构举例:高扇出的模块结构举例: 编外 人员 工资 取得 工资 数据 计时 制工 资额 薪金 制工 资额 编外 人员 税款 编外 人员 扣款 常规 扣款 税收 扣款 计算实发工资 避免平铺结构 37 编外 人员 工资 取得工 资数据 计时 制工 资额 薪金 制工 资额 编外 人员 税款 编外 人员
8、扣款 常规 扣款 税收 扣款 计算实发工资 计时工人 实发工资 计薪工人 实发工资 编外人员 实发工资 增加中间层降低扇出 38 模块的作用域定义为受该模块内一个判模块的作用域定义为受该模块内一个判 定影响的所有模块的集合。模块的控制定影响的所有模块的集合。模块的控制 域是这个模块本身以及所有直接或间接域是这个模块本身以及所有直接或间接 从属于它的模块的集合。从属于它的模块的集合。 模块模块C C的控制范围的控制范围: C: C、D D、E E、F F、G G、H,H, 如果模块如果模块C C 作出的决策影响了模块作出的决策影响了模块L L,L L 超出了超出了C C 的控制范围的控制范围.
9、.(难于理解;会(难于理解;会 出现控制耦合)出现控制耦合) 1 1、把做决策的点、把做决策的点C C上移上移 2 2、把、把L L移到移到C C的控制域中的控制域中 在一个设计得很好的系统中,所有受判在一个设计得很好的系统中,所有受判 定影响的模块应该都从属于做出判定的定影响的模块应该都从属于做出判定的 那个模块,最好局限于做出判定的那个那个模块,最好局限于做出判定的那个 模块本身及它的直属下级模块。模块本身及它的直属下级模块。 4. 模块的作用域应该在控制域之内 C H DE G X F AI L JKB 39 模块接口复杂是软件发生错误的一个主要原因 模块接口复杂是软件发生错误的一个主要
10、原因 。应该仔细设计模块接口,使得信息传递简单并且。应该仔细设计模块接口,使得信息传递简单并且 和模块的功能一致。和模块的功能一致。 接口复杂或不一致接口复杂或不一致( (即看起来传递的数据之间即看起来传递的数据之间 没有联系没有联系) ),是紧耦合或低内聚的征兆,是紧耦合或低内聚的征兆,应该重新,应该重新 分析这个模块的独立性。分析这个模块的独立性。 5. 力争降低模块接口的复杂程 度 40 这条启发式规则警告软件工程师 这条启发式规则警告软件工程师不要使不要使 模块间出现内容耦合模块间出现内容耦合。当从顶部进入模块并。当从顶部进入模块并 且从底部退出来时,软件是比较容易理解的且从底部退出来
11、时,软件是比较容易理解的 ,因此也是比较容易维护的。,因此也是比较容易维护的。 6. 设计单入口单出口的模块 41 模块的功能应该能够预测,但也要防止模块功 模块的功能应该能够预测,但也要防止模块功 能过分局限。能过分局限。 如果一个模块可以当做一个黑盒子,也就是说 如果一个模块可以当做一个黑盒子,也就是说 ,只要输入的数据相同就产生同样的输出只要输入的数据相同就产生同样的输出,这个模,这个模 块的功能就是可以预测的。带有内部块的功能就是可以预测的。带有内部“ “存储器存储器” ”的模的模 块的功能可能是不可预测的,因为它的输出可能取块的功能可能是不可预测的,因为它的输出可能取 决于内部存储器
12、决于内部存储器( (例如某个标记例如某个标记) )的状态。由于内部的状态。由于内部 存储器对于上级模块而言是不可见的,所以这样的存储器对于上级模块而言是不可见的,所以这样的 模块既不易理解又难于测试和维护。模块既不易理解又难于测试和维护。 7. 模块功能应该可以预测 42 5.4 描绘软件结构的图形工具 层次图 43 HIPO图(可追踪) IPO图来描述 处理过程 44 结构图 循环循环 调用调用 条件条件 调用调用 模块的名字或 主要功能 调用关系 传递的信息(数 据流和控制流) 45 5.5 面向数据流的设计方法(结构化设 计 方法SD) 面向数据流的设计方法的目标是给出设计软件结面向数据流的设计方法的目标是给出设计软件结 构的一个系统化的途径。构的一个系统化的途径。 面向数据流的设计方法定义了一些不同的面向数据流的设计方法定义了一些不同的“ “映射映射” ” ,利用这些映射可以把数据流图变换成软件结构,利