内聚和耦合的区别

内聚和耦合之间的区别是什么?

耦合和内聚如何导致软件设计的好坏?

举些什么例子来概括这两者之间的区别,以及它们对整体代码质量的影响?

431731 次浏览

在面向对象编程语言中,高内聚模块和低耦合之间的模块通常被认为与高质量有关。

例如,每个Java类中的代码必须具有较高的内部内聚性,但要尽可能地与其他Java类中的代码松散耦合。

Meyer的面向对象软件构建(第二版)的第3章很好地描述了这些问题。

凝聚力指的是类(或模块)可以做什么。低内聚意味着这个类会做各种各样的动作——它很宽泛,不关注它应该做什么。高内聚意味着类专注于它应该做的事情,即只有与类的意图相关的方法。

低内聚的例子:

-------------------
| Staff           |
-------------------
| checkEmail()    |
| sendEmail()     |
| emailValidate() |
| PrintLetter()   |
-------------------

高内聚的例子:

----------------------------
| Staff                   |
----------------------------
| -salary                 |
| -emailAddr              |
----------------------------
| setSalary(newSalary)    |
| getSalary()             |
| setEmailAddr(newEmail)  |
| getEmailAddr()          |
----------------------------

至于耦合,它指的是两个类/模块彼此之间的关联或依赖程度。对于低耦合类,改变一个类中的主要内容不应该影响到另一个类。高耦合会使更改和维护代码变得困难;由于类紧密地结合在一起,因此进行更改可能需要对整个系统进行改造。

好的软件设计有高内聚低耦合

提高内聚性和降低耦合确实会带来好的软件设计。

内聚对功能进行了划分,使其简洁并与相关数据最接近,而解耦则确保功能实现与系统的其余部分隔离。

解耦允许您在不影响软件其他部分的情况下更改实现。

凝聚力确保实现更特定于功能,同时更易于维护。

减少耦合和增加内聚的最有效方法是界面设计

也就是说,主要的功能对象只能通过它们实现的接口相互“认识”。接口的实现自然会引入内聚性。

虽然在某些场景中不太现实,但这应该是一个设计目标。

例子(非常粗略):

public interface IStackoverFlowQuestion
void SetAnswered(IUserProfile user);
void VoteUp(IUserProfile user);
void VoteDown(IUserProfile user);
}


public class NormalQuestion implements IStackoverflowQuestion {
protected Integer vote_ = new Integer(0);
protected IUserProfile user_ = null;
protected IUserProfile answered_ = null;


public void VoteUp(IUserProfile user) {
vote_++;
// code to ... add to user profile
}


public void VoteDown(IUserProfile user) {
decrement and update profile
}


public SetAnswered(IUserProfile answer) {
answered_ = answer
// update u
}
}


public class CommunityWikiQuestion implements IStackoverflowQuestion {
public void VoteUp(IUserProfile user) { // do not update profile }
public void VoteDown(IUserProfile user) { // do not update profile }
public void SetAnswered(IUserProfile user) { // do not update profile }
}

在你的代码库的其他地方,你可以有一个模块来处理问题,不管它们是什么:

public class OtherModuleProcessor {
public void Process(List<IStackoverflowQuestion> questions) {
... process each question.
}
}

凝聚力在软件工程中是某个模块的元素属于一起的程度。因此,它是软件模块的源代码所表达的每个功能之间相关性的一种度量。

简单地说,耦合是一个组件(同样,想象一个类,尽管不一定)对另一个组件的内部工作方式或内部元素的了解程度,即它对另一个组件的了解程度。

我为此写了一篇博客,如果你想阅读更多的例子和图纸的细节。我想它回答了你的大部分问题。

凝聚力的最佳解释来自Bob叔叔的Clean Code:

类应该有少量的实例变量。类的每个方法都应该操作一个或多个这样的变量。一般来说,一个方法操作的变量越多,该方法对其类的内聚性就越强。每个方法使用每个变量的类具有最大的内聚性。

一般来说,创建这种最大限度内聚的类既不可取,也不可能;另一方面,我们希望内聚能力高。当内聚性高时,这意味着类的方法和变量是相互依赖的,并作为一个逻辑整体挂在一起。

保持函数小和参数列表短的策略有时会导致由方法子集使用的实例变量激增。当这种情况发生时,几乎总是意味着至少有一个其他类试图从较大的类中退出。您应该尝试将变量和方法分离到两个或多个类中,以便新类更具内聚性。

我认为区别可以归结为以下几点:

  • 内聚表示代码库的一部分在逻辑上形成单一原子单元的程度。
  • 耦合表示单个单元独立于其他单元的程度。
  • 在不破坏内聚的情况下存档完全解耦是不可能的,反之亦然。

在这篇博文中我写得更详细。

凝聚力表示模块的相对功能强度。

    内聚模块执行单一任务,要求很少 与程序其他部分中的其他组件交互。所述 简单地说,一个内聚模块(理想情况下)应该只做一件事
  • < p >传统观点:

    模块的“专一性”

  • < p >OO视图:

    【内聚性】意味着一个组件或类只封装彼此密切相关以及与类或组件本身密切相关的属性和操作

  • )内聚水平

    功能

    层

    交往的

    顺序

    程序

    颞

    效用< / p >

耦合表示模块之间的相对依赖关系。

  • 耦合取决于模块之间的接口复杂度 指向一个模块的条目或引用,以及什么数据

  • .通过接口传递
  • 常规视图: 一个组件与其他组件和外部世界的连接程度

  • OO视图:类之间连接程度的定性度量

  • 耦合水平

    内容

    常见

    控制

    邮票

    数据

    程序调用

    类型使用

    包含或导入

    外部# < / p >

凝聚力表示软件元素的职责是如何相关和集中的。

耦合表示软件元素与其他元素的连接强度。

软件元素可以是类、包、组件、子系统或系统。在设计系统时,建议使用具有高内聚并支持低耦合的软件元素。

低凝聚力将导致难以维护、理解并降低可重用性的单一类。类似地,高耦合导致类紧密耦合,更改往往不是非本地的,难以更改并减少了重用。

我们可以假设一个场景,我们正在设计一个典型的可监视ConnectionPool,具有以下需求。请注意,对于ConnectionPool这样的简单类来说,它可能看起来太多了,但基本目的只是用一些简单的示例演示低耦合高内聚,我认为应该有帮助。

  1. 支持连接
  2. 释放连接
  3. 获取有关连接与使用计数的统计数据
  4. 获取有关连接和时间的统计数据
  5. 将连接检索和发布信息存储到数据库中,以便以后报告。

使用低凝聚力,我们可以设计一个ConnectionPool类,将所有这些功能/职责强制填充到一个单独的类中,如下所示。我们可以看到,这个类负责连接管理、与数据库交互以及维护连接统计信息。

低内聚连接池

使用高内聚,我们可以跨类分配这些职责,并使其更可维护和可重用。

高内聚连接池

为了演示低耦合,我们将继续上面的高内聚ConnectionPool图。如果我们看一下上面的图表,尽管它支持高内聚性,但ConnectionPoolConnectionStatistics类紧密耦合,PersistentStore类直接与它们交互。相反,为了减少耦合,我们可以引入ConnectionListener接口,让这两个类实现该接口,并让它们注册到ConnectionPool类中。ConnectionPool将遍历这些侦听器,并通知它们连接获取和释放事件,从而减少耦合。

Low Coupling ConnectionPool

对于这个简单的场景,它可能看起来有点多余,但如果我们想象一个实时场景,我们的应用程序需要与多个第三方服务交互来完成一个事务:直接将我们的代码与第三方服务耦合将意味着第三方服务中的任何更改都可能导致我们的代码在多个地方发生更改,相反,我们可以让Facade在内部与这些多个服务交互,而对服务的任何更改都成为Facade的本地,并强制与第三方服务进行低耦合。

耦合 =两个模块之间的交互/关系… 内聚 =模块内两个元素之间的相互作用。

软件是由许多模块组成的。模块由元素组成。把一个模块看作一个程序。程序中的函数是一个元素。

在运行时,一个程序的输出被用作另一个程序的输入。这称为模块与模块之间的交互或流程与流程之间的通信。这也称为耦合。

在单个程序中,函数的输出被传递给另一个函数。这称为模块内元素的交互。这也被称为内聚。

例子:

耦合 =两个不同家庭之间的沟通… 凝聚力 =家庭中父亲、母亲和孩子之间的沟通。

凝聚力(凝聚力):有限公司意味着在一起hesion意味着坚持。粘结:不同物质的微粒粘在一起的系统

< p > # EYZ0 < br > # EYZ0 < br > # EYZ0 < / p >

整体大于部分之和-亚里士多德。

  • 内聚是一种序数类型的测量,通常被描述为“高内聚”或“低内聚”。具有高内聚性的模块往往更可取,因为高内聚性与软件的几个理想特性有关,包括健壮性、可靠性、可重用性和可理解性。相反,低内聚与一些不受欢迎的特性有关,例如难以维护、测试、重用,甚至难以理解。wiki

  • <强>耦合通常与<强>内聚形成对比。低耦合通常与高内聚相关,反之亦然。低耦合通常是结构良好的计算机系统和良好设计的标志,当与高内聚相结合时,可以支持高可读性和可维护性的总体目标。wiki

简单地说,凝聚力意味着一个类应该代表一个概念。

如果类的所有特征都与类所代表的概念相关,则类的公共接口是内聚的。 例如,与其拥有CashRegister类,不如拥有CashRegister和Coin特性,将其整合为2个类- CashRegister和Coin类

耦合中,一个类依赖于另一个类,因为它使用类的对象。

高耦合的问题在于它会产生副作用。一个类中的一个更改可能导致另一个类中出现意外错误,并可能破坏整个代码。

通常,高内聚和低耦合被认为是高质量的OOP。

简单地说,凝聚力表示代码库的一部分在逻辑上形成单个原子单元的程度。另一方面,耦合表示单个单元对其他单元的依赖程度。换句话说,它是两个或多个单元之间的连接数。数量越少,耦合越低。

本质上,高内聚意味着将代码库中相互关联的部分保存在一个地方。同时,低耦合是关于尽可能多地分离代码库中不相关的部分。

从内聚和耦合角度来看的代码类型:

理想的是遵循准则的代码。它是松散耦合和高度内聚的。我们可以用下面的图片来说明这样的代码:enter image description here

上帝的对象是引入高内聚和高耦合的结果。它是一种反模式,基本上代表一段一次性完成所有工作的代码: enter image description here 发生在不同类或模块之间的边界选择不佳enter image description here

破坏性的解耦是最有趣的一个。它有时发生在程序员试图解耦代码库的时候,以至于代码完全失去了它的焦点:enter image description here

阅读更多在这里

术语凝聚力在软件设计中确实有点违背直觉。

聚合力通常的意思是某物粘在一起很好,是统一的,其特征是像分子吸引力一样的强结合。然而,在软件设计中,这意味着力求类在理想情况下只做一件事,因此甚至不涉及多个子模块。

也许我们可以这样想。当一个部分是唯一的部分(只做一件事并且不能进一步分解)时,它具有最大的内聚性。这就是软件设计所需要的。内聚只是“单一责任”或“关注点分离”的另一种说法。

术语耦合是非常直观的,这意味着当一个模块不依赖于太多其他模块,并且它所连接的模块可以很容易地被替换,例如遵循利斯科夫替换原理

enter image description here

内聚指的是单个类如何设计。内聚是面向对象的原则,它与确保类的设计具有单一的、重点明确的目的密切相关。 一个班级越集中,它的凝聚力就越强。高内聚性的优点是,与低内聚性的类相比,这样的类更容易维护(并且更改频率更低)。高内聚性的另一个好处是具有良好目标的类往往比其他类更具可重用性

在上图中,我们可以看到,在低内聚情况下,只有一个类负责执行大量不相同的作业,这降低了可重用性和维护的机会。但是在高内聚的情况下,所有的作业都有一个单独的类来执行特定的作业,这样可以获得更好的可用性和可维护性。

理论的区别

凝聚力

  • 内聚性是模块相对功能强度的表征。
  • 内聚模块执行单一任务,很少需要与其他模块交互 . . 具有高内聚和低耦合的模块称为功能独立模块 其他模块。李< / >

衔接的分类

1.巧合2。逻辑3。时间4。程序5。沟通6。连续7。功能

耦合

  • 耦合表示模块之间的相对依赖关系。
  • 两个模块之间的耦合程度取决于它们的接口复杂性。
内聚表示模块内部的关系,而耦合表示模块之间的关系。提高内聚性对软件有利,但要避免增加软件的耦合性。 内聚性表示模块的功能强度。耦合表示模块之间的独立性。在内聚中,模块专注于单个事物。在耦合中,模块连接到其他模块。所以,在设计时,你应该努力实现高内聚和低耦合