为什么紧密耦合不好但强烈打字好?

JLX*_*JLX 9 strong-typing loose-coupling

我很难看到松耦合代码的真实好处.为什么花费这么多精力使灵活的东西与各种其他物体一起工作?如果你知道你需要实现什么,为什么不专门为此目的编码?

对我来说,这类似于创建无类型变量:它使它变得非常灵活,但是它可能会导致问题,因为可能传入了一个意外的值.它也使得它更难阅读,因为你没有明确知道传入的是什么.

然而我觉得强烈打字是受鼓励的,但松散耦合是不好的.

编辑:我觉得我对松散耦合的解释是关闭还是其他人正在以错误的方式阅读它.与我的强耦合是当一个类引用另一个类的具体实例时.松散耦合是指类引用另一个类可以实现的接口.

那么我的问题是为什么不专门调用类的具体实例/定义?我将其类比为具体定义您需要的变量类型.我一直在阅读关于依赖注入的一些内容,他们似乎认为松散耦合更好的设计是事实.

Dav*_*nco 15

首先,你将苹果与橙子进行比较,让我试着从两个角度来解释这个问题.键入是指如何对值/变量执行操作以及是否允许它们.与内聚相反,耦合是指一个(或几个)软件的体系结构.这两者根本没有直接关系.

强弱与弱打字

强类型语言(通常)是一件好事,因为行为定义得很好.从维基百科中获取这两个例子:

打字不好:

a = 2
b = '2'

concatenate(a, b) # Returns '22'
add(a, b)         # Returns 4
Run Code Online (Sandbox Code Playgroud)

上面的内容可能有点令人困惑,而且定义不太明确,因为有些语言可能会使用ASCII(可能是十六进制,也许是八进制等)数值来进行添加或连接,因此有很多空间可以解决错误.此外,很难看出a原来是integera还是a string(这可能很重要,但语言并不关心).

强类型:

a = 2
b = '2'

#concatenate(a, b)     # Type Error
#add(a, b)             # Type Error
concatenate(str(a), b) # Returns '22'
add(a, int(b))         # Returns 4
Run Code Online (Sandbox Code Playgroud)

正如您在此处所看到的,一切都更明确,您知道变量是什么,以及何时更改任何变量的类型.

维基百科说:

弱类型声称的优点是程序员需要的工作量少于编程器,因为编译器或解释器隐式执行某些类型的转换.然而,一个声称的缺点是弱类型编程系统在编译时捕获较少的错误,并且其中一些可能在测试完成后仍然存在.支持多种隐式转换的两种常用语言是C和C++,有时声称它们是弱类型语言.然而,其他人认为这些语言对如何混合不同类型的操作数有足够的限制,这两种应该被视为强类型语言.

强类型和弱类型都有其优点和缺点,既不好也不坏.了解差异和相似之处非常重要.

松散与紧耦合

直接来自维基百科:

在计算机科学中,耦合或依赖是每个程序模块依赖于其他每个模块的程度.

耦合通常与凝聚力形成对比.低耦合通常与高内聚相关,反之亦然.耦合和凝聚力的软件质量指标是由结构化设计的原始开发人员Larry Constantine发明的,他也是这些概念的早期支持者(另见SSADM).低耦合通常是结构良好的计算机系统和良好设计的标志,并且当与高内聚相结合时,支持高可读性和可维护性的一般目标.

简而言之,低耦合是代码非常紧凑,可读和可维护的标志.在处理大量API或大型项目时,高耦合是首选,其中不同的部分交互形成整体.既不好也不坏.有些项目应紧密耦合,即嵌入式操作系统.其他人应该松散耦合,即网站CMS.

希望我在这里说清楚:)


Jor*_*ger 6

需要指出的问题是正确的,弱/动态类型的确是松耦合概念的逻辑扩展,并且程序员偏爱其中一种而不是另一种是不一致的。

松散耦合已成为流行语,许多程序员不必要地实现接口和依赖项注入模式 -或更常见的是,他们自己的这些模式的乱码版本-取决于未来需求可能会发生一些不确定的变化。不能掩盖这样的事实,它会引入额外的复杂性,并使将来的开发人员难以维护代码。唯一的好处是,如果这种预期的松散耦合碰巧使需求的未来更改更易于实现,或者促进了代码重用。但是,需求变更通常会涉及系统的各个层次,从UI到存储,从根本上来说,松散耦合根本不会提高设计的健壮性,并使某些类型的琐碎变更变得更加乏味。


Pao*_*tta 5

你是对的,松散耦合在编程中几乎被普遍认为是“好”的。为了理解原因,让我们看一下紧耦合的一个定义:

如果A必须仅仅因为B改变而改变,那么你说AB紧密耦合。

这是一个从“完全解耦”(即使B消失了,A将保持不变)到“松散耦合”(B 的某些变化可能会影响A,但大多数进化变化不会)到“非常紧密”的尺度耦合”(对B 的大多数更改都会深深影响A)。

在 OOP 中,我们使用了很多技术来减少耦合——例如,封装有助于将客户端代码与类的内部细节解耦。此外,如果您依赖于一个接口,那么您通常不必担心对实现该接口的具体类的更改。

附带说明一下,打字和耦合是相关的,你是对的。特别是,更强和更静态的类型往往会增加耦合。例如,在动态语言中,您有时可以用字符串代替数组,这是基于字符串可以被视为字符数组的概念。在 Java 中你不能,因为数组和字符串是不相关的。这意味着如果 B 过去返回一个数组而现在返回一个字符串,它肯定会破坏它的客户端(只是一个简单的人为例子,但你可以想出更多更复杂和更引人注目的例子)。因此,更强的类型和更多的静态类型都是权衡。虽然强类型通常被认为是好的,但偏爱静态类型还是动态类型在很大程度上取决于上下文和个人品味:

所以最后我们可以回到你最初的问题:为什么通常认为松散耦合是好的?因为不可预见的变化。当您编写系统时,您不可能知道它在两个月或两个小时内最终会向哪个方向发展。发生这种情况的原因既是因为需求会随着时间而变化,也因为您通常不会完全了解系统,直到之后你已经写好了。如果您的整个系统非常紧密地耦合(这种情况有时被称为“大泥球”),那么系统每个部分的任何更改最终都会波及系统的每个其他部分(“非常”的定义)紧耦合”)。这使得非常不灵活的系统最终结晶成一个刚性的、不可维护的斑点。如果您在开始处理系统的那一刻就拥有 100% 的远见,那么您就不需要解耦。

另一方面,正如您所观察到的,解耦是有代价的,因为它增加了复杂性。更简单的系统更容易改变,因此程序员面临的挑战是在简单和灵活之间取得平衡。紧耦合通常(并非总是)使系统更简单,但代价是使其更加刚性。大多数开发人员低估了未来对更改的需求,因此常见的启发式方法是使系统的耦合程度低于您想要的程度,只要这不会使其过于复杂。


Kev*_*ker 2

如果您知道需要实现什么,为什么不专门为此目的编写代码。

简短的回答:你几乎永远不知道自己需要实现什么目标。需求发生变化,如果您的代码一开始就是松散耦合的,那么适应起来就不那么困难了。

  • 现在你假设有一个结局;) (2认同)