“低耦合和高凝聚力”是什么意思


151

我在理解该声明时遇到困难low in coupling and high in cohesion。我已经在Google上搜索并阅读了很多相关内容,但仍然很难理解。

据我了解High cohesion,这意味着我们应该具有专门用于执行特定功能的类。希望这是正确的?类似于信用卡验证类,该类专门用于仅验证信用卡。

仍然不了解低耦合是什么意思?


4
有关更详细的说明,您可以喜欢本文的答案凝聚力与耦合
Infinity

这个答案肯定比这里给出的答案更好,更简洁。
罗克什

实际上,这是这些的重复。到目前为止,Infinity答案是唯一未提及的重复项目。
cellepo

Answers:


232

我相信的是:

内聚性是指模块/类的元素相互之间的结合程度,建议相关的代码应彼此靠近,因此我们应争取较高的内聚力,并将所有相关的代码尽可能地绑定在一起。它与元素做的模块/类。

耦合是指不同模块/类之间相互依赖的程度,建议所有模块都应尽可能独立,这就是低耦合的原因。它与不同模块/类之间的元素有关。

可视化整个图片将有所帮助:

在此处输入图片说明

屏幕截图来自Coursera


20
我们的教授说:“高内聚性是关于确保模块不会做很多事情,这意味着只能做一件特定的事情”。
罗克什

2
我认为,这更像是“确保一个模块执行某件事,没有多个模块完成同一件事”,通过这种方式,您可以确保只有一个模块指定行为,因此,事物的整体行为具有凝聚力。
sschrass

5
@Lokesh我认为您的评论使事情变得混乱。您的教授将高度凝聚力与“单一责任原则”混为一谈。高凝聚力意味着将相似和相关的事物保持在一起。在由许多功能组成的对象或服务中,您可以具有很高的凝聚力。
Max Hodges

17
该图实际上没有任何意义。
利亚姆'18

1
就微服务架构而言,高凝聚力意味着紧密相关的事物应在一个微服务中保持在一起,而松散耦合则意味着微服务本身应被细化以在有限的上下文中工作,即独立地做一件事情。
sactiw

41

就像在现实生活中一样,软件工程的凝聚力是可以说组成一个整体(在我们的情况下,我们说一个类)的元素实际上属于同一元素的程度。因此,它衡量了由软件模块的源代码表达的每个功能之间的关联程度。

从OO角度看内聚的一种方法是,如果类中的方法使用任何私有属性。

现在讨论的范围比这个要大,但是内聚力(或内聚力的最佳类型-功能内聚力)是将模块的各个部分归为一组,因为它们都对模块的一个明确定义的任务有所贡献。

简单来说,耦合就是一个组件(尽管不是必须的,再想一想一个类)对另一组件的内部运作或内部元素了解多少,即它对另一组件具有多少知识。

松散耦合是一种将系统或网络中的组件互连的方法,以使这些组件在实际可行的范围内以最小的程度相互依赖……

我写了一篇关于这个的博客文章。它通过示例等详细讨论了所有这些内容。它还解释了为什么遵循这些原则的好处。


26

在软件设计中,高凝聚力意味着类应该很好地完成一件事和一件事。高凝聚力与单一责任原则密切相关。

低耦合表明类应该具有最小的依赖关系。另外,必须存在的依赖项应该是弱的依赖项-优先考虑对接口的依赖性,而不是对具体类的依赖性,或者优先于继承而不是继承。

高内聚和低耦合为我们提供了更好设计的代码,更易于维护。


您错过了依赖注入。它与低耦合紧密相关,以确保类具有最少/没有依赖性。
BugHunterUK

16

简短明了的答案

  • 高凝聚力:一个类/模块中的元素应该在功能上属于同一类,并且做一件特定的事情。
  • 松耦合:在不同的类/模块之间应该有最小的依赖性。

9

低耦合是在两个或多个模块的上下文中。如果一个模块的更改导致另一模块的许多更改,则可以说它们是高度耦合的。这是基于接口的编程帮助的地方。模块内的任何更改都不会影响其他模块,因为它们之间的接口(交互作用的平均值)没有更改。

高凝聚力-将类似的东西放在一起。因此,一个类应该具有方法或行为来完成相关工作。仅举一个夸张的坏例子:List接口的实现不应具有与String相关的操作。String类应具有与String相关的方法,字段,并且类似地,List的实现应具有相应的内容。

希望有帮助。


5

长话短说,低耦合度据我所知,这意味着可以更换组件而不会影响系统的正常运行。基本上将您的系统调制为可正常运行的组件,这些组件可以单独更新而不会破坏系统


1
这与高凝聚力不一样吗?
user1315906

4

你有智能手机吗?有一个大应用程序还是有很多小应用程序?一个应用会回复另一个吗?您可以在安装,更新和/或卸载另一个应用程序时使用一个应用程序吗?每个应用程序都是独立的,具有很高的凝聚力。每个应用程序都独立于其他应用程序是低耦合的。DevOps支持此体系结构,因为它意味着您可以进行离散的连续部署而不会破坏整个系统。


>一个应用程序会回复另一个吗?。。好吧,有些。许多应用程序使用“相机”应用程序,通过锻炼应用程序将心脏和锻炼数据馈入“健康和活动”。我可以将一个应用的摘要分享给其他许多应用。我的闹钟应用知道时间,并可以从“音乐”应用中播放曲目...
Max Hodges,

@MaxHodges,该东西(低内聚和高耦合)已被贬值,应尽可能最小化。正如您提到的,在某些情况下。这不能完全删除。
哈比卜

2

继承或概括是高度耦合(即高度相互依赖)的一个示例。我的意思是,在继承中,父类通常会定义其子类使用的基本功能,并且父类的方法更改会直接影响其子类。因此,我们可以说类之间存在更大程度的相互依赖。

实现或使用接口是高内聚性(即低相互依赖性)的一个示例。这意味着接口为实现该接口的任何类提出了合同,但是每个类都有权以自己的方式实现在接口中声明的方法,并且在一个类中声明的方法的更改不会影响其他任何类。


2

凝聚力 -一切之间的紧密联系。
耦合 -一切如何相互连接。

让我们举个例子-我们要设计一种自动驾驶汽车。

(1)我们需要电动机正常运行。

(2)我们需要汽车自行驾驶。

(1)中的所有类和功能都可以使电动机启动并使电动机一起运转,但不会帮助汽车转向。因此,我们将这些类放在引擎控制器后面。

(2)中的所有类和功能都可以使汽车转向,加速和制动。它们不会帮助汽车启动或将汽油输送到活塞。因此,我们将这些类放在其自己的Driving Controller之后。

这些控制器用于与所有可用的类和功能进行通信。然后,控制器仅相互通信。这意味着我无法从油门踏板类中调用活塞类中的函数来使汽车行驶更快。

踏板课程必须要求驾驶控制器与发动机控制器对话,然后告诉发动机控制器更快地行驶。这使我们的程序员能够发现问题,并使我们能够组合大型程序而不必担心。这是因为代码都在控制器后面工作。


1

低耦合和高内聚是推荐的现象。

耦合意味着各种模块在何种程度上相互依赖,以及其他模块在更改某个模块的某些/重要功能时会受到怎样的影响。强调低耦合,因为必须保持较低的依存关系,以便对其他模块进行非常小/可忽略的更改。


1

一个例子可能会有所帮助。想象一下一个系统,该系统生成数据并将其放入数据存储,可以是磁盘上的文件,也可以是数据库。

通过将数据存储代码与数据生产代码分开,可以实现高内聚性。(实际上是将磁盘存储与数据库存储分开)。

通过确保数据生产对数据存储没有任何不必要的了解(例如,不询问数据存储有关文件名或数据库连接的信息),可以实现低耦合。


1

这是一些抽象的图形理论角度的答案:

让我们通过仅查看有状态对象之间的(定向)依赖图来简化问题。

通过考虑依赖图的两个限制情况,可以说明一个非常简单的答案 :

第一种极限情况聚类图

聚类图是高内聚和低耦合(给定的聚类大小)依赖性图的最完美实现。

群集之间的依赖性最大(完全连接),群集间的依赖性最小(零)。

这是其中一种极限情况下答案的抽象图示。

第二个极限情况是一个完全连通的图,其中一切都取决于一切。

在我的拙劣理解中,现实介于两者之间,离集群图越近越好。

从另一个角度来看:当查看有向依存关系图时,理想情况下它应该是非循环的,否则循环将形成最小的群集/组件。

层次结构的上/下一级对应于松耦合,紧密内聚的“一个实例”,但是可以将这种松耦合/紧密内聚的原理视为在非循环有向图的不同深度处重复的现象(或其生成树之一)。

将系统分解为层次结构有助于克服指数级的复杂性(例如,每个集群有10个元素)。然后在6层,已经是100万个对象:

10个集群构成1个超集群,10个集群构成1个超集群,依此类推...如果没有紧密的凝聚力,松散耦合的概念,那么这种分层体系结构将是不可能的。

因此,这可能是故事的真正重要性,而不仅仅是两层中的高内聚性低耦合。在考虑更高级别的抽象及其交互时,真正的重要性变得很明显。



0

低耦合:-将使其保持非常简单。如果更改模块,它将如何影响其他模块。

示例:-如果您的服务API公开为JAR,则对方法签名的任何更改都将中断调用API(高/紧耦合)。

如果您的模块和其他模块通过异步消息进行通信。只要您收到消息,您的方法更改签名就在您的模块本地(低耦合)。

偏离航路时,如果消息格式发生更改,则呼叫客户端将需要进行一些更改。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.