模块独立性由两个定性标准度量
- 模块自身的内聚
- 模块之间的耦合
内聚性分类:
- 偶然性内聚(最不好的一种内聚):模块内的各个任务在功能上没有实质性联系,纯属“偶然”因素组合了块内各个互不相关的任务。
一个处理正方形的模块有两个功能:计算面积,画出这个正方形。
改进:分成两个模块,计算面积和画出正方形
- 逻辑性内聚:模块通常由若干个逻辑功能相似的任务组成,通过模块外引入的一个开关量选择其一执行。这种内聚增大了模块间的耦合。
一个模块负责打印季度开支报告、月份开支报告和日开支报告,具体打印哪一个报告由传入的控 制标志决定,这个模块具有逻辑性内聚。
改进:建立三个模块分别负责打印季度开支报告、月份开支报告和日开支报告。改进原来的模 块,根据传入的控制标志来调用这三个模块中的一个。
- 时间性内聚:模块内的各个任务由相同的执行时间联系在一起。
特点:同时进行,并非顺序执行。
初始化模块,紧急故障处理模块。
-
过程性内聚:模块内的各个任务必须按照某一特定次序执行。
特点:控制流从一个动作 —> 另一个动作
- 通信性内聚:模块内部的各个任务靠公用数据联系在一起,即都使用同一个输入数据,或者产生同一个输出数据。
如果是根据员工出生日期分别计算员工年龄和退休时间,该模块就具有通信性内聚(同一个输入数据)。
改进:改成两个模块:根据员工出生日期算员工年龄从一个处理单元流到另一个和根据员工出生日期算退休时间。
-
顺序性内聚:模块内的各个任务是顺序执行的。通常,上一个任务的输出是下一个任务的输入。
特点:数据流从一个处理单元流到另一个处理单元。
模块根据员工出生日期计算员工年龄,再由员工年龄计算其退休时间,该模块就具有顺序性内聚
改进:改成两个模块,把功能分解。
- 功能性内聚:模块各个成分结合在一起,完成一个特定的功能。功能性模块具有内聚性最强、与其他模块联系少的特点。
一个模块根据员工出生日期计算员工年龄,该模块具有功能性内聚。
耦合性分类
- 非直接耦合:同级模块相互之间没有信息传递,属于非直接耦合。
- 数据耦合:调用下属模块时,如果交换的都是简单变量,便构成数据耦合。
- 特征耦合:调用下属模块时,如果交换的是数据结构,便构成特征耦合。
由于传递的是数据结构,不仅数据量增加,而且会使模块的相关性增加。
- 控制耦合:模块间传递的信息不是一般的数据,而是作为控制信息的开关值或标志量。 逻辑性内聚的模块的调用就是控制耦合。
- 外部耦合:若允许一组模块访问同一个全局变量,可称它们为外部耦合。
松散的公共耦合 紧密的公共耦合
- 公共耦合:若允许一组模块访问同一个全局性的数据结构,则称它们为公共耦合。
全局性的数据结构可以是共享的通信区、公共的内存区域、任何存储介质文件、物理设备等。
- 内容耦合:若一个模块可以直接访问另一个模块中的内部数据,或者一个模块直接转到另一个模块的内部,或者一个模块有多个入口,则称为内容耦合。
是最强的耦合,往往是被称为“病态”的块间联系。
例: class A {
public int m;
}
class B{
A a = new A();
a. m += 1;
}
应改为
class A {
private int m;
}