内聚和耦合之间的区别是什么?
耦合和内聚如何导致软件设计的好坏?
举些什么例子来概括这两者之间的区别,以及它们对整体代码质量的影响?
内聚和耦合之间的区别是什么?
耦合和内聚如何导致软件设计的好坏?
举些什么例子来概括这两者之间的区别,以及它们对整体代码质量的影响?
当前回答
关于内聚的最好解释来自Bob叔叔的《Clean Code》:
类应该有少量的实例变量。类的每个方法都应该操作一个或多个这样的变量。一般来说,方法操作的变量越多,该方法与其类的内聚性就越强。每个方法使用每个变量的类具有最大的内聚性。
一般来说,创建这种最大限度内聚的类既不可取,也不可能;另一方面,我们希望内聚力高。当内聚性高时,这意味着类的方法和变量是相互依赖的,并作为一个逻辑整体挂在一起。
保持函数小和参数列表短的策略有时会导致由方法子集使用的实例变量激增。当这种情况发生时,几乎总是意味着至少有一个其他类试图从较大的类中退出。您应该尝试将变量和方法分离到两个或多个类中,以便新类更具内聚性。
其他回答
内聚这个术语在软件设计中确实有点违背直觉。
聚合力通常的意思是某物粘在一起很好,是统一的,其特征是像分子吸引力一样的强结合。然而,在软件设计中,这意味着力求类在理想情况下只做一件事,因此甚至不涉及多个子模块。
也许我们可以这样想。当一个部分是唯一的部分(只做一件事并且不能进一步分解)时,它具有最大的内聚性。这就是软件设计所需要的。内聚只是“单一责任”或“关注点分离”的另一种说法。
术语耦合是非常直观的,这意味着当一个模块不依赖于太多其他模块时,它所连接的那些模块可以很容易地被替换,例如遵循利斯科夫替换原理。
内聚性是一个模块相对功能强度的指示。
A cohesive module performs a single task, requiring little interaction with other components in other parts of a program. Stated simply, a cohesive module should (ideally) do just one thing. Conventional view: the “single-mindedness” of a module OO view: cohesion implies that a component or class encapsulates only attributes and operations that are closely related to one another and to the class or component itself Levels of cohesion Functional Layer Communicational Sequential Procedural Temporal utility
耦合表示模块之间的相对相互依赖。
耦合取决于模块之间的接口复杂性 指向一个模块的条目或引用,以及什么数据 通过接口传递。 传统观点: 一个组件与其他组件和外部世界的连接程度 OO视图:类之间连接程度的定性度量 耦合水平 内容 常见 控制 邮票 数据 程序调用 类型使用 包含或导入 外部#
在面向对象编程语言中,模块内部的高内聚和模块之间的低耦合通常被认为与高质量有关。
例如,每个Java类中的代码必须具有较高的内部内聚性,但要尽可能地与其他Java类中的代码松散耦合。
Meyer的面向对象软件构建(第二版)的第3章对这些问题进行了很好的描述。
内聚性表明了软件元素的职责是如何相互关联和集中的。
耦合指的是软件元素与其他元素的连接强度。
软件元素可以是类、包、组件、子系统或系统。在设计系统时,建议使用具有高内聚性和支持低耦合的软件元素。
低内聚导致整体类难以维护、理解,降低了可重用性。类似地,高耦合导致类紧密耦合,更改往往不是非局部的,难以更改并减少重用。
我们可以假设一个场景,在这个场景中,我们正在设计一个典型的可监视ConnectionPool,并满足以下需求。注意,对于像ConnectionPool这样的简单类来说,它可能看起来太过了,但基本目的只是用一些简单的示例演示低耦合和高内聚,我认为应该会有所帮助。
支持连接 释放连接 获取有关连接与使用计数的统计数据 获取有关连接和时间的统计数据 将连接检索和发布信息存储到数据库中,以便以后报告。
对于低内聚,我们可以通过将所有功能/职责强制填充到单个类中来设计ConnectionPool类,如下所示。我们可以看到,这个类负责连接管理、与数据库交互以及维护连接统计信息。
有了高内聚性,我们可以在类之间分配这些职责,并使其更可维护和可重用。
To demonstrate Low coupling we will continue with the high cohesion ConnectionPool diagram above. If we look at the above diagram although it supports high cohesion, the ConnectionPool is tightly coupled with ConnectionStatistics class and PersistentStore it interacts with them directly. Instead to reduce the coupling we could introduce a ConnectionListener interface and let these two classes implement the interface and let them register with ConnectionPool class. And the ConnectionPool will iterate through these listeners and notify them of connection get and release events and allows less coupling.
Note/Word or Caution: For this simple scenario it may look like an overkill but if we imagine a real-time scenario where our application needs to interact with multiple third party services to complete a transaction: Directly coupling our code with the third party services would mean that any changes in the third party service could result in changes to our code at multiple places, instead we could have Facade that interacts with these multiple services internally and any changes to the services become local to the Facade and enforce low coupling with the third party services.
内聚指的是类(或模块)可以做什么。低内聚意味着这个类会做各种各样的动作——它很宽泛,不关注它应该做什么。高内聚意味着类专注于它应该做的事情,即只有与类的意图相关的方法。
低内聚的例子:
-------------------
| Staff |
-------------------
| checkEmail() |
| sendEmail() |
| emailValidate() |
| PrintLetter() |
-------------------
高内聚的例子:
----------------------------
| Staff |
----------------------------
| -salary |
| -emailAddr |
----------------------------
| setSalary(newSalary) |
| getSalary() |
| setEmailAddr(newEmail) |
| getEmailAddr() |
----------------------------
至于耦合,它指的是两个类/模块彼此之间的关联或依赖程度。对于低耦合类,改变一个类中的主要内容不应该影响到另一个类。高耦合会使更改和维护代码变得困难;由于类紧密地结合在一起,因此进行更改可能需要对整个系统进行改造。
好的软件设计具有高内聚性和低耦合性。