内聚和耦合有什么区别?
耦合和内聚如何导致软件设计的好坏?
有哪些示例概述了两者之间的差异及其对整体代码质量的影响?
答案 0 :(得分:610)
Cohesion 指的是类(或模块)可以执行的操作。低凝聚力意味着班级做了各种各样的行动 - 它是广泛的,没有关注它应该做什么。高凝聚力意味着课程专注于应该做的事情,即只有与课堂意图相关的方法。
低凝聚力的例子:
-------------------
| Staff |
-------------------
| checkEmail() |
| sendEmail() |
| emailValidate() |
| PrintLetter() |
-------------------
高凝聚力的例子:
----------------------------
| Staff |
----------------------------
| -salary |
| -emailAddr |
----------------------------
| setSalary(newSalary) |
| getSalary() |
| setEmailAddr(newEmail) |
| getEmailAddr() |
----------------------------
对于耦合,它指的是两个类/模块相互依赖或相互依赖的方式。对于低耦合类,更改一个类中的主要内容不应该影响另一个类。高耦合会使您难以更改和维护代码;由于课程紧密结合在一起,因此进行更改可能需要对整个系统进行改造。
良好的软件设计具有高内聚和低耦合。
答案 1 :(得分:69)
模块中的高内聚和模块之间的低耦合通常被认为与OO编程语言中的高质量相关。
例如,每个Java类中的代码必须具有高内部内聚力,但是尽可能松散地耦合到其他Java类中的代码。
Meyer's Object-Oriented Software Construction (2nd edition)的第3章是对这些问题的一个很好的描述。
答案 2 :(得分:51)
凝聚力表示模块中的关系。
耦合表示模块之间的关系。
<强>衔接强>
<强>联轴器强>
检查this链接
答案 3 :(得分:47)
凝聚力表明软件元素的职责是如何相关和集中的。
耦合是指软件元素与其他元素的连接强度。
软件元素可以是类,包,组件,子系统或系统。在设计系统时,建议使用高内聚并支持低耦合的软件元素。
低内聚会导致整体类难以维护,理解并降低可重用性。类似地,高耦合会导致紧密耦合的类,并且更改往往不是非本地的,难以更改并且会减少重用。
我们可以假设我们正在设计一个具有以下要求的典型可监控ConnectionPool
。请注意,对于像ConnectionPool
这样的简单类来说,它看起来可能太多了,但基本意图只是用一些简单的示例演示低耦合和高内聚我认为应该有所帮助。
通过低内聚,我们可以通过将所有这些功能/职责强制填充到单个类中来设计ConnectionPool
类,如下所示。我们可以看到这个单一类负责连接管理,与数据库交互以及维护连接统计信息。
凭借高凝聚力,我们可以在各个班级中分配这些责任,使其更易于维护和重复使用。
为了演示低耦合,我们将继续使用上面的高内聚ConnectionPool
图表。如果我们查看上图,虽然它支持高内聚性,ConnectionPool
与ConnectionStatistics
类紧密耦合,PersistentStore
它与它们直接交互。相反,为了减少耦合,我们可以引入一个ConnectionListener
接口,让这两个类实现接口,让它们在ConnectionPool
类中注册。并且ConnectionPool
将遍历这些侦听器并通知它们连接get和release事件并允许更少的耦合。
注意/单词或注意:对于这个简单的场景,它可能看起来像是一种矫枉过正,但如果我们想象一个实时场景,我们的应用程序需要与多个第三方服务进行交互以完成交易:将我们的代码与第三方服务直接耦合意味着第三方服务中的任何更改都可能导致我们的代码在多个位置发生更改,而我们可能会Facade
在内部与这些多个服务进行交互以及任何更改服务变为Facade
的本地服务,并强制与第三方服务低度耦合。
答案 4 :(得分:31)
增加内聚力和减少耦合会导致良好的软件设计。
Cohesion对您的功能进行分区,使其简洁且最接近与其相关的数据,同时解耦确保功能实现与系统的其余部分隔离。
Decoupling 允许您更改实施,而不会影响软件的其他部分。
Cohesion 可确保实施更具体功能,同时更易于维护。
减少耦合和增加内聚力的最有效方法是通过接口设计。
这是主要功能对象应该只通过它们实现的接口“相互”“知道”。界面的实现引入了凝聚力作为一种自然结果。
虽然在某些情况下不太现实,但应该是设计目标。
示例(非常粗略):
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.
}
}
答案 5 :(得分:24)
类应该有少量的实例变量。类的每个方法都应该操纵这些变量中的一个或多个。 通常,方法操作的变量越多,该方法对其类的内聚性越强。每个方法使用每个变量的类具有最大的内聚性。
一般来说,创建这样最具凝聚力的课程既不可取也不可能;另一方面,我们希望凝聚力很高。当内聚力很高时,这意味着类的方法和变量是相互依赖的,并且作为一个逻辑整体挂在一起。
保持函数较小并使参数列表保持简短的策略有时会导致方法子集使用的实例变量激增。当发生这种情况时,它几乎总是意味着至少有一个其他类试图离开更大的类。您应该尝试将变量和方法分成两个或更多个类,以便新类更具凝聚力。
答案 6 :(得分:11)
耦合简单来说,一个组件(再次,想象一个类,虽然不一定)知道另一个组件的内部工作或内部元素,即它有多少知识另一个组成部分。
I wrote a blog post about this,如果您想通过示例和图纸阅读更多细节。我认为它回答了你的大多数问题。
答案 7 :(得分:4)
简单地,内聚力表示部分代码库形成一个逻辑上单一的原子单元的程度。另一方面,耦合表示单个单元彼此独立的程度。换句话说,它是两个或多个单元之间的连接数。数字越少,耦合越低。
本质上,高内聚性意味着将彼此相关的代码库部分放在一个地方。同时,低耦合意味着尽可能多地分离代码库的无关部分。
从内聚和耦合的角度看代码类型:
理想是遵循该准则的代码。它是松散耦合的,并且具有高度的凝聚力。我们可以通过以下图片来说明这样的代码:
上帝对象是引入高凝聚力和高耦合的结果。它是一种反模式,基本上代表着一次性执行所有工作的一段代码: 选择不佳发生在不同类别或模块之间的边界选择不当
破坏性去耦是最有趣的一种。有时,当程序员试图使代码库脱钩而导致代码完全失去焦点时,有时会发生这种情况:
了解更多here
答案 8 :(得分:3)
内聚力涉及单个类的设计方式。内聚性是与确保类以单一且重点突出的目的进行设计紧密相关的面向对象原则。 一个班级越集中,该班级的凝聚力就越大。高内聚性的优点是,此类类比低内聚性类更易于维护(且更改频率较低)。高凝聚力的另一个好处是,目的明确的课程比其他课程更易于重用。
在上图中,我们可以看到,在低内聚性中,只有一个类负责执行很多不常见的工作,从而减少了重用和维护的机会。但是,由于具有很高的凝聚力,所有作业都有一个单独的类来执行特定作业,因此可以提高可用性和维护性。
答案 9 :(得分:2)
凝聚力(Co-hesion): Co 表示在一起, hesion ,这意味着到粘即可。将不同物质的颗粒粘在一起的系统。
对于现实生活中的例子:
img Courtesy
整体大于部分之和 - 亚里士多德。
答案 10 :(得分:1)
我认为差异可以如下:
In this blog post我更详细地写了这篇文章。
答案 11 :(得分:1)
Cohesion 表示模块的相对功能强度。
传统观点:
模块的“一心一意”
OO观点:
cohesion意味着组件或类仅封装彼此密切相关的属性和操作以及类或组件本身
内聚水平
Functional
Layer
Communicational
Sequential
Procedural
Temporal
utility
耦合表明模块之间的相对依赖性。
耦合取决于模块之间的接口复杂性 指向模块的入口或引用以及哪些数据 通过界面。
传统观点: 组件与其他组件和外部世界连接的程度
OO观点:对班级彼此联系程度的定性衡量
耦合程度
Content
Common
Control
Stamp
Data
常规电话
类型使用
包含或导入
外部#
答案 12 :(得分:1)
耦合 =两个模块之间的互动/关系...... Cohesion =模块中两个元素之间的交互。
软件由许多模块组成。模块由元素组成。考虑一个模块是一个程序。程序中的函数是一个元素。
在运行时,程序的输出用作另一个程序的输入。这称为模块到模块的交互或过程来处理通信。这也称为耦合。
在单个程序中,函数的输出传递给另一个函数。这称为模块内元素的交互。这也称为凝聚力。
示例:
耦合 =两个不同家庭之间的沟通...... 凝聚力 =在家庭中的父母 - 孩子之间进行交流。
答案 13 :(得分:0)
简单地说,内聚力意味着一个类应该代表一个概念。
如果所有类功能都与该类所代表的概念相关,则该类的公共接口是内聚的。 例如,不具有CashRegister类,而是具有CashRegister和Coin功能的内聚性使其分为2类-CashRegister和Coin类。
在耦合中,一个类依赖于另一类,因为它使用该类的对象。
高耦合的问题在于它会产生副作用。一个类中的一个更改可能会导致另一类中的意外错误,并可能破坏整个代码。
通常,高内聚和低耦合被认为是高质量的OOP。
答案 14 :(得分:0)
凝聚力一词在软件设计中的含义确实有点反常。
内聚力的共同含义是,可以很好地粘合在一起的东西是统一的,其特征是像分子吸引力那样的牢固结合。但是,在软件设计中,这意味着争取一个只做一件事的类,因此甚至不涉及多个子模块。
也许我们可以这样想。当零件是唯一零件时,它具有最大的凝聚力(仅做一件事,无法进一步细分)。这是软件设计中所需要的。凝聚力只是“单一责任”或“关注点分离”的别称。
手上的“ 耦合”一词非常直观,这意味着当一个模块不依赖太多其他模块并且可以轻松替换与之连接的模块时,例如遵循{{3} }。
答案 15 :(得分:0)
1。偶然的2.逻辑的3.时间的4.程序的5.沟通的6.顺序的7.功能的