第八讲 软件设计的启发式规则 面向数据流的设计方法
第八讲 软件设计的启发式规则 面向数据流的设计方法
软件设计的启发式规则 2启发式规则是一种经验规律 对改进设计和提高软件质量 具有重要的参考价值,但不 要过分拘泥于这些规则 7.设计功能可以模块
一、软件设计的启发式规则 1. 提高模块独立性 2. 设计规模适中的模块 3. 深度、宽度、扇入、扇出适中 4. 模块的作用域应该在控制域之内 5. 降低接口复杂性 6. 设计单入口和单出口的模块 7. 设计功能可以预测的模块 启发式规则是一种经验规律, 对改进设计和提高软件质量 具有重要的参考价值,但不 要过分拘泥于这些规则
1)提高模块独立性 是划分模块的最高准则。 高内聚,尽量一个模块一个功能; 低耦合,避免“病态连接”; 降低接口的复杂程度; 综合考虑模块可分解性、模块可组装性 模块可理解性、模块连续性和模块保护 (因修改错误而引起的副作用被控制在 模块的内部)等
1) 提高模块独立性 • 是划分模块的最高准则。 • 高内聚,尽量一个模块一个功能; • 低耦合,避免“病态连接”; • 降低接口的复杂程度; • 综合考虑模块可分解性、模块可组装性、 模块可理解性、模块连续性和模块保护 (因修改错误而引起的副作用被控制在 模块的内部)等
2)设计规模适中的模块 W. M. Weinberg的研究表明:如果一个模块 长度超过30条语句,其可理解性将迅速下降; F.T. Baker:最好控制在50行左右,能够打印 在一张纸上。 由于模块独立性是最高原则,对于一个设计 合理的功能性模块,即使长达千句或小到几 行,也是允许的 分解模块不应该降低模块独立性
2) 设计规模适中的模块 • W. M. Weinberg的研究表明:如果一个模块 长度超过30条语句,其可理解性将迅速下降; • F. T. Baker : 最好控制在50行左右,能够打印 在一张纸上。 • 由于模块独立性是最高原则,对于一个设计 合理的功能性模块,即使长达千句或小到几 行,也是允许的。 • 分解模块不应该降低模块独立性
3)深度、宽度、扇入、扇出适中 深度:软件结构中控制的层数。一般而 它与系统的复杂度和系统大小直接对应 宽度:软件结构中同一个层次上的模块总 数的最大数。 扇出:一个模块直接控制(调用)的模块 数目。扇出过大说明模块过分复杂;过小 也不好,不利于系统平衡分解,3到9为宜 扇入:一个模块的扇入是指直接控制该模 块的模块数目。扇入越大说明共享该模块 的上级模块越多 整个系统结构呈现“椭圆外型
3) 深度、宽度、扇入、扇出适中 • 深度:软件结构中控制的层数。一般而言 它与系统的复杂度和系统大小直接对应。 • 宽度:软件结构中同一个层次上的模块总 数的最大数。 • 扇出:一个模块直接控制(调用)的模块 数目。 扇出过大说明模块过分复杂;过小 也不好,不利于系统平衡分解,3到9为宜。 • 扇入:一个模块的扇入是指直接控制该模 块的模块数目。扇入越大说明共享该模块 的上级模块越多。 • 整个系统结构呈现“椭圆外型
如图的系统中:深度为4;宽度为5;模块A的扇出 为5,扇入为0。模块K的扇出为0;扇入为2。 A B D E F H K
A B C D F G H I J K E 如图的系统中:深度为4;宽度为5;模块A的扇出 为5,扇入为0。模块K的扇出为0;扇入为2
4)模块的作用域应在控制域之内 控制域:控制范围,是包括模块本身以及 所有下属模块(直接调用模块和间接调用 模块)的集合 作用域:作用范围,它是一个与条件判定 相联系的概念。是受该模块内一个判定影 响的所有模块的集合 对作用域不在控制域的两种改进方法:判 定上移和在作用域但不在控制域的模块下 移
4) 模块的作用域应在控制域之内 • 控制域:控制范围,是包括模块本身以及 所有下属模块(直接调用模块和间接调用 模块)的集合。 • 作用域:作用范围,它是一个与条件判定 相联系的概念。是受该模块内一个判定影 响的所有模块的集合。 • 对作用域不在控制域的两种改进方法:判 定上移和在作用域但不在控制域的模块下 移
A 模块D的控制域为 D, G,H,I, J K D E 如果D中有一个条件判 H定仅影响到模块G和H, 其作用域为G,H,L,J,K 作用域在控制域内 K 如果D中判定影响到E,通常需在D为判定结果设置 标记,并把该标记通过上级模块A传递给E,导 致控制耦合。其作用域为D.G,H,I,JK和,作用 域在控制域内
A C D G H I J K E 如果D中判定影响到E,通常需在D为判定结果设置 一标记,并把该标记通过上级模块A传递给E,导 致控制耦合。其作用域为D,G, H, I, J, K和E ,作用 域在控制域内。 模块D的控制域为 D,G,H,I,J, K。 如果D中有一个条件判 定仅影响到模块G和H, 其作用域为G, H, I, J, K , 作用域在控制域内
5)降低接口复杂性 尽量少用goto,避免病态连接和内容耦合 注意全局变量的使用,控制外部耦合和公共 耦合的使用。 将数据结构的传递改成数据传递,例如:在 求一元二次方程根的模块 quad root(able,X) 中,利用系数数组 Table和根数组X进行参数 传递。如果将其改为直接的系数和根传递, 即 quad root(a,b,c,x1x2),则特征耦合→数据 耦
5) 降低接口复杂性 • 尽量少用go to,避免病态连接和内容耦合。 • 注意全局变量的使用,控制外部耦合和公共 耦合的使用。 • 将数据结构的传递改成数据传递,例如:在 求一元二次方程根的模块quad_root(Table, X) 中,利用系数数组Table和根数组X进行参数 传递。如果将其改为直接的系数和根传递, 即quad_root(a, b, c, x1 ,x2 ),则特征耦合→数据 耦合
6)设计单入口和单出口的模块 符合结构化程序设计的思想 应避免病态连接和内容耦合。 “一个功能一个模块”→提高软件的可读 性和可理解性 有效阻断“涟漪效应( ripple effect→提高 软件的可靠性和可维护性
6) 设计单入口和单出口的模块 • 符合结构化程序设计的思想 • 应避免病态连接和内容耦合。 • “一个功能一个模块”→提高软件的可读 性和可理解性。 • 有效阻断“涟漪效应(ripple effect)” →提高 软件的可靠性和可维护性