“低耦合高内聚”是啥意思

Posted

技术标签:

【中文标题】“低耦合高内聚”是啥意思【英文标题】:What does 'low in coupling and high in cohesion' mean“低耦合高内聚”是什么意思 【发布时间】:2012-12-09 15:51:34 【问题描述】:

我无法理解声明 low in coupling and high in cohesion。我已经用谷歌搜索并阅读了很多关于此的内容,但仍然很难理解。

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

还是不明白低耦合是什么意思?

【问题讨论】:

更详细的解释,你可以优先选择这篇帖子的答案Cohesion & Coupling This answer 肯定比这里给出的更好更简洁。 事实上,这是一个副本。到目前为止,Infinity 的回答是唯一没有提到的非重复项。 【参考方案1】:

长话短说,我理解的低耦合意味着可以在不影响系统正常运行的情况下更换组件。基本上将您的系统模块化为可以在不破坏系统的情况下单独更新的功能组件

【讨论】:

不就是和高内聚一样吗?【参考方案2】:

我认为是这样的:

内聚是指一个模块/类的元素相互归属的程度,建议相关的代码应该相互靠近,所以要争取高内聚,将所有相关的代码尽可能紧密地绑定在一起可能的。它与模块/类的元素有关。

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

可视化整个图片会很有帮助:

截图来自Coursera。

【讨论】:

我们的教授说“高内聚力是要确保模块不会做很多事情,它意味着只做一件特定的事情”。 我认为这更像是“确保一个模块做一件事,而不是很多模块做同样的事情”,这样你可以确保只有一个模块指定行为,所以事物的整体行为具有凝聚力。 @Lokesh 我认为您的评论使事情变得混乱。您的教授将高凝聚力与“单一责任原则”混淆了。高内聚意味着将相似和相关的事物保持在一起。您可以在由许多功能组成的对象或服务中具有高内聚性。 该图实际上没有任何意义。 就微服务架构而言,高内聚意味着强相关的东西应该放在一个微服务中,而松耦合意味着微服务本身应该细粒度以有界地工作上下文即独立做一件事。【参考方案3】:

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

耦合意味着各种模块在多大程度上相互依赖,以及其他模块如何影响模块的某些/相当大的功能。强调低耦合,因为必须保持低依赖性,以便对其他模块进行非常少/可忽略的更改。

【讨论】:

【参考方案4】:

低耦合是在两个或多个模块的上下文中。如果一个模块的变化导致另一个模块的许多变化,那么它们被称为高度耦合。这就是基于接口的编程有帮助的地方。模块内的任何更改都不会影响其他模块,因为它们之间的接口(交互的意思)没有改变。

高凝聚力——把相似的东西放在一起。所以一个类应该有方法或行为来完成相关的工作。举个夸张的坏例子:List接口的实现不应该有与String相关的操作。 String类应该有与String相关的方法、字段,同样,List的实现也应该有对应的东西。

希望对您有所帮助。

【讨论】:

【参考方案5】:

凝聚力在软件工程中,就像在现实生活中一样,是指组成一个整体(在我们的例子中,假设是一个类)的元素有多少可以说它们实际上属于一起。因此,它是衡量一个软件模块的源代码所表达的每个功能的关联程度。

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

现在讨论的范围远不止于此,但 高内聚(或内聚的最佳类型 - 功能内聚)是将模块的各个部分分组,因为它们都有助于单个明确定义的任务模块。

耦合 简单来说,就是一个组件(再次,想象一个类,虽然不一定)对另一个组件的内部运作或内部元素了解多少,即它拥有多少知识另一个组件。

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

I wrote a blog post 关于这个。它通过示例等详细讨论了所有这些。它还解释了为什么应该遵循这些原则的好处。

【讨论】:

【参考方案6】:

在软件设计中高内聚意味着班级应该把一件事和一件事做好。高内聚与Single responsibility principle密切相关。

低耦合建议类应该有尽可能少的依赖关系。此外,必须存在的依赖项应该是弱依赖项——更喜欢对接口的依赖而不是对具体类的依赖,或者更喜欢组合而不是继承。

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

【讨论】:

你错过了依赖注入。它与低耦合密切相关,以确保一个类具有最少/没有依赖关系。【参考方案7】:

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

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

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

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

你有智能手机吗?是有一个大应用程序还是很多小应用程序?一个应用程序会回复另一个应用程序吗?您可以在安装、更新和/或卸载另一个应用程序时使用一个应用程序吗?每个应用程序都是独立的,这是高度内聚的。每个应用程序都独立于其他应用程序是低耦合的。 DevOps 青睐这种架构,因为这意味着您可以在不中断整个系统的情况下进行离散的持续部署。

【讨论】:

>一个应用程序会回复另一个应用程序吗? . .嗯,是的,有些人这样做。许多应用程序使用相机应用程序,通过锻炼应用程序将心脏和锻炼数据提供给健康和活动。我可以将一个应用程序的 sn-p 共享给许多其他应用程序。我的闹钟应用知道时间并从音乐应用播放曲目... @MaxHodges 东西(低内聚和高耦合)已被贬低,应尽可能减少。在某些情况下,正如您所提到的。这无法完全删除。【参考方案10】:

简短而清晰的答案

高内聚度:一个类/模块中的元素在功能上应该属于一起并做一件特定的事情。 松散耦合:不同的类/模块之间的依赖应该是最小的。

【讨论】:

【参考方案11】:

凝聚力 - 一切事物之间的关系有多密切。耦合 - 一切事物之间的关系如何。

举个例子——我们想设计一辆自动驾驶汽车。

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

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

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

(2) 中的所有类和函数都非常适合使汽车转向、加速和制动。它们不帮助汽车启动或向活塞输送汽油。所以我们把这些类放在它自己的驾驶控制器后面。

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

踏板类必须要求驾驶控制器与引擎控制器对话,然后引擎控制器会告诉活塞类加快速度。这让我们程序员能够发现问题,让我们可以毫无顾虑地组合大型程序。这是因为代码都在控制器后面工作。

【讨论】:

【参考方案12】:

这是从一个抽象的图论角度给出的答案:

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

一个非常简单的答案可以通过考虑两个limiting cases 的依赖图来说明:

第一个限制情况:cluster graphs。

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

簇间的依赖最大(全连接),簇间的依赖最小(零)。

这是limiting cases 之一中答案的抽象插图。

第二个限制情况是一个全连接图,其中一切都依赖于一切。

现实介于两者之间,在我的拙见中,越接近集群图越好。

从另一个角度来看:在查看有向依赖图时,理想情况下它应该是非循环的,如果不是,则循环形成最小的集群/组件。

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

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

10 个集群形成 1 个超集群,10 个超集群形成 1 个超集群等等……如果没有紧密内聚、松耦合的概念,这样的分层架构是不可能的。

所以这可能是故事的真正重要性,而不仅仅是两层内的高内聚低耦合。当考虑更高级别的抽象及其交互时,真正的重要性变得清晰。

【讨论】:

【参考方案13】:

我认为你有这么多的定义,但如果你仍然有疑问,或者如果你是编程新手并想深入了解,那么我建议你观看这个视频, https://youtu.be/HpJTGW9AwX0 它只是获取有关多态性的更多信息的参考... 希望您对此有更好的理解

【讨论】:

【参考方案14】:

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

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

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

如果消息格式发生变化,呼叫客户端将需要进行一些更改。

【讨论】:

【参考方案15】:

以旧 PC 主板为例。

鼠标有自己的 PS/2 端口。 打印机有自己的打印机端口。 显示器有自己的 VGA 端口。

这意味着特定端口仅用于特定设备,而不是其他设备。

这是强/高耦合

由于鼠标仅用于操作光标和相关功能,键盘用于键入键等,即它们仅执行其预期的任务,这是高凝聚力

如果鼠标有几个按钮 'a' 'b' 'c' 可以输入,那么它所做的比它应该做的要多,因为键盘已经在执行它们,这是 低凝聚力

谢天谢地,专用端口的过时用法被我们称为 USB 的标准(接口)所取代。这是松散/低耦合

看看这些物理属性,很明显这就是它应该的样子,但是在编写软件时很容易忘记将什么功能放在哪里等等,因此提醒一下,在生活中的每一件事上,始终坚持:

'高内聚和松耦合'

【讨论】:

【参考方案16】:

打个比方,如果你的猫,它的凝聚力,如果你的狗需要一只猫在他身边吠,它是高度耦合的。

“狗吠猫叫,如果它们发出你的拉取请求将被拒绝”

【讨论】:

以上是关于“低耦合高内聚”是啥意思的主要内容,如果未能解决你的问题,请参考以下文章

高内聚低耦合

面向对象三大特性五大原则 + 低耦合高内聚

面向对象之低耦合,高内聚

低耦合,高内聚。实乃至理名言

《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》

面向对象三大特性五大原则 + 低耦合高内聚