模块化
耦合
描述了两个模块之间关系的复杂程度。耦合越低,模块的划分就越好,越有利于软件的变更与复用。
结构化设计中的耦合 重点
类型 | 解释 | 举例 |
---|---|---|
内容耦合 最高 | 一个模块直接修改或者依赖于另一个模块的内容。 | 跳转语句;改变另一个模块的代码。 |
公共耦合 | 模块之间共享全局的数据。 | 全局变量。 |
重复耦合 | 模块之间有同样逻辑的重复代码。 | ctrl+C/ctrl+V 的时候。 |
控制耦合 | 一个模块传递给另一个模块控制信息。 | 传递一种控制消息,如给另一个模块 disp Sun ,另一个模块显示 星期天 。 |
印记耦合 | 共享一个数据结构,但只使用了一部分。 | 如给另一个模块 {day: Sun, date: 2024-6-9} ,另一个模块显示 星期天 。 |
数据耦合 最低 | 两个模块的所有参数是同类的数据项。 | 给另一个模块 星期天 ,另一个模块显示 这是星期天 。 |
内容耦合、公共耦合和重复耦合是不可接受的,必须消除掉;数据耦合是最好的。
面向对象设计的耦合 重点
面向对象中类和类的联系相比结构化设计更加规范化和复杂化。因此,有下面两种更细化更特殊的耦合。
访问耦合
在面向对象方法中,如果类
类型 | 解释 | 举例 |
---|---|---|
隐式访问 最高 | ||
实现中访问 | 避免隐式访问的方法。 | |
成员变量访问 | ||
参数变量访问 | ||
无访问 最低 | 完全不访问。 | 完全独立。 |
继承耦合
类型 | 解释 |
---|---|
修改 最高 | 子类修改从父类继承来的接口或实现。 |
精化 | 子类根据已经定义好的规则来修改父类的接口或实现。 |
扩展 | 子类只增加新的方法和成员变量,不对从父类继承来的方法与成员变量进行修改。 |
无继承 | 两个类之间不继承。 |
内聚
描述了一个模块内部联系的紧密程度。内聚越高,模块的划分就越好,越有利于软件的变更与复用。
结构化设计中的内聚 重点
类型 | 解释 | 举例 |
---|---|---|
偶然内聚 最低 | 模块执行多个不相干的操作。 | {修车, 烤面包, 看电影} |
逻辑内聚 | 模块执行一系列相关操作,但由其他模块来决定具体调用。 | {看电影, 看书, 看戏剧} |
时间内聚 | 模块执行一系列与时间有关的操作。 | {起床, 刷牙, 吃饭} |
过程内聚 | 模块执行一系列与步骤顺序有关的操作。强调逻辑联系。 | {买票, 去车站, 检票, 上车} |
通信内聚 | 模块执行一系列与相同数据相关的操作,并与步骤有关。 | {查找书名, 查找作者, 查找出版商} |
功能内聚 | 模块执行一个操作或达到单一的目的。 | 一个算法,如最短路径 、最大流 等。 |
信息内聚 最高 | 模块执行许多操作,各自有自己的入口点,但所有操作都在同一数据上进行。 | 数据结构中的栈 、队列 等。 |
面向对象设计中的内聚 重点
面向对象设计中的内聚分为方法内聚、类的内聚和继承内聚。方法内聚与结构化相近。类的内聚主要是衡量成员变量和成员方法的内聚。而继承内聚考虑了继承树中的内聚性。其中,类的内聚要做到:
- 方法和属性一致。
- 属性之间体现一个职责。
信息隐藏
基本思想
每个模块都承担一定的职责,对外表现为一份契约,并在这份契约之下隐藏着只有这个模块才知道的设计决策或秘密(这一决策通常是容易发生改变的)。
信息隐藏的决策 重点
- 职责的实现;
- 实现的变更。