软件设计 耦合
耦合是一种软件度量标准,它描述两个例程或模块之间的紧密程度。 这是质量的度量。 该概念由拉里·康斯坦丁(Larry Constantine)在1960年代提出,并在1974年的《 IBM系统期刊,结构化设计》和1979年的同名书中得到了体现。
拥有模块A和B,需要更多有关B的知识才能理解A,A与B之间的联系也就越紧密。需要检查一个模块以了解另一个模块的操作这一事实表明:互连程度,即使互连程度未知。
耦合是互连强度的度量。 耦合受模块之间的连接类型,接口复杂性,模块连接之间的信息流以及模块连接的绑定时间影响。 耦合通常与凝聚力形成对比,例如,低耦合会转化为高凝聚力,反之亦然。
耦合水平
耦合可以是低/松/弱或高/紧/强。
进行更改时,紧密耦合会转化为涟漪效应,以及难以理解的代码。 当一个模块的行为不正确时,它倾向于在模块之间传播错误。 它往往使调试和修复缺陷复杂化。
另一方面,在松耦合系统中,可以研究和更改单个模块,而无需考虑来自其他模块的大量信息。 错误可以更容易指出。 调试花费的时间更少,而修复缺陷通常更简单。 跨模块错误传播的机会往往会减少。
下面的耦合级别从高到低排序:
- 内容耦合 :当一个模块修改或依赖于另一个模块的内部工作时,就会发生内容耦合或病理耦合。 更改内部工作将导致需要更改从属模块。 一个搜索方法就是将未找到的对象添加到用于保存信息的数据结构的内部结构中。
- 通用耦合 :当两个或多个函数共享全局数据时,就会发生全局耦合。 对它们的任何更改都会产生连锁React。 全局耦合的一个示例是有关操作的全局信息状态,其中多个模块对该位置进行读写。
- 控制耦合 :当一个模块通过传递控制信息(例如,控制标志,传递给排序算法的比较函数)来控制另一个模块的流程时,就会发生控制耦合。
- 邮票耦合 :邮票耦合或数据结构耦合发生在模块共享复合数据结构并仅使用其中一部分(可能是不同部分)的情况下。 一个示例是一个打印模块,它接受一个实体,并检索其信息以构造一条消息。
- 数据耦合 :当方法通过参数定期共享数据时,就会发生数据耦合。 数据耦合比标记耦合好,因为模块可以准确地获取所需的信息,而无需知道特定数据结构的结构。
- 消息耦合 :消息耦合是耦合的最低形式,通过分散和消息传递来实现。 示例包括依赖注入和可观察对象。
耦合度量
班级
类级别的耦合是由于系统中的实现依赖关系导致的。 通常,一个类别对另一类别做出的假设越多,耦合就越紧密。
耦合的强度由类的稳定性(即,如果类发生更改需要在从属类中进行的更改量)以及访问范围(即访问类的范围)来确定,更大的范围引入了更紧密的耦合。 在课程级别,耦合度是通过传递的消息数与收到的消息数之比来衡量的,即
DC = MRC / MPC
其中, MRC
是接收到的消息耦合(一个类从其他类接收到的消息数), MPC
是传递的消息耦合(一个类向其他类发送的消息数)。
类级别是模块级别指标的一种特殊情况。
模块级别
作为更一般的指标,此指标跟踪其他模块,全局数据和外部环境。 该公式计算模块指标mc
,其中
mc = k /米
其中k
为比例常数, M
为通过以下公式计算的值:
M = di +(a * ci)+ d0 +(b * c0)+ gd + c * gc)+ w + r
在上面的公式中:
-
a
,b
和c
凭经验定义 -
w
–称为(扇出)的模块数量–r
–所考虑的模块(扇入)的调用模块数量是环境耦合参数 -
gd
和gc
描述了用作数据和控件的全局变量的数量,它们是全局耦合参数 -
di
,do
,ci
和co
,描述数据的数量以及控制输入和输出参数,是数据和控制流参数
需要注意的重要一点是,随着mc
值的增加,整体耦合减小。 为了使耦合随着耦合程度的增加而向上移动,可以将修订后的耦合度量C
定义为
C = 1 – mc
去耦
引入耦合会增加系统的不稳定性。 解耦是模块之间的系统耦合减少,其明确意图是使模块更加独立,即,如上一节中所定义的,将C
的值最小化。
通过以下封装可以消除内容耦合。
通用耦合可以通过引入抽象来解决。 设计模式可能对实现良好的体系结构很有用。
外部耦合可以通过消除领域中格式的知识并在概念上进行操作来解决。
可以通过使用策略或状态来消除控制耦合。
可以通过传递实际数据来消除图章耦合。
通过使用消息传递可以消除数据耦合。
减少耦合的一个非常重要的原则是如下的Demeter定律 。
得墨meter耳定律
Demeter定律也称为最小知识原理,是松耦合的一种特殊情况。 该原则指出,一个单元只应了解并与紧密相关的单元对话,并尽可能少地考虑与之交互的任何事物的结构和属性,包括其自身的子组件。 例如,对象A可以调用对象B的功能,但不应通过B来访问对象C的功能。 相反,对象B应该通过其自己的接口促进访问,从而将请求传播到其子组件。 或者,A可以直接引用C。
更为正式的定义指出,对象O上的方法M可以调用以下对象的方法:
- Ø
- M的参数
- 在M中创建/实例化的任何对象
- O的直接子组件
- M范围内的O可以访问的全局变量
特别是,对象不应在返回的对象上调用方法,即,代码中最多应有一个点,例如a.Method()而不是aBMethod()。
结论
耦合是不可避免的。 否则,每个模块将是其自己的程序。 但是,实现低耦合应该是系统设计的主要目标之一,这样就可以研究和更改单个模块,而无需考虑其他模块的大量信息,可以更轻松地指出错误,并且调试花费的时间更少,而修复缺陷通常更简单。
松散的耦合会导致高内聚性,并且它们一起会导致可维护的系统。
参考资料
翻译自: https://www.javacodegeeks.com/2016/08/thoughts-coupling-software-design.html
软件设计 耦合