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

时间:2010-10-30 05:30:29

标签: strong-typing loose-coupling

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

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

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

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

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

9 个答案:

答案 0 :(得分:15)

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

强而弱的打字

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

打字错误

a = 2
b = '2'

concatenate(a, b) # Returns '22'
add(a, b)         # Returns 4

上面的内容可能有点令人困惑,而且定义不太明确,因为某些语言可能会使用ASCII(可能是十六进制,也许是八进制等)数值来进行添加或连接,因此有很多空间可以解决错误。此外,很难看出a最初是integer还是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

正如你在这里看到的,一切都更明确,你知道变量是什么,以及当你改变任何变量的类型时。

维基百科说:

  

声称弱打字的优势   是因为它需要更少的努力   程序员的一部分,因为   隐式地使用编译器或解释器   执行某些类型的转换。   然而,一个声称的缺点是   弱类型编程系统   在编译时捕获更少的错误   其中一些可能仍然存在   测试已经完成。二   常用的语言支持   多种隐式转换   C和C ++,有时会声称   这些是弱类型的语言。   然而,其他人认为这些   语言有足够的限制   如何操作不同类型的操作数   混合,这两个应该被视为   作为强类型语言。

强而弱的打字既有优点也有缺点,既不好也不坏。了解差异和相似之处非常重要。

松散与紧耦合

直接来自维基百科

  

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

     

耦合通常与之形成鲜明对比   凝聚。经常低耦合   与高凝聚力相关,并且   反之亦然。软件质量   耦合和凝聚力的指标是   由拉里康斯坦丁发明的   结构化的原始开发者   设计谁也是早期的支持者   这些概念(另见SSADM)。   低耦合通常是a的标志   结构良好的计算机系统和   良好的设计,并结合使用   高凝聚力,支持一般   高可读性的目标   可维护性。

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

希望我在这里说清楚一点:)

答案 1 :(得分:5)

正确的问题是指出弱/动态类型确实是松散耦合概念的逻辑扩展,并且程序员偏向于一个而不是另一个是不一致的。

松散耦合已成为一个流行语,many programmers unnecessarily implementing interfaces and dependency injection patterns - 或者,通常是他们自己的这些模式的乱码版本 - 基于未来需求的某些无定形变化的可能性。没有隐藏这一事实,这会带来额外的复杂性,并使代码对于未来的开发人员而言难以维护。唯一的好处是,如果这种预期的松散耦合恰好使得需求的未来变化更容易实现,或促进代码重用。然而,通常情况下,需求变化涉及系统的足够层次,从UI到存储,松散耦合根本不会提高设计的稳健性,并使某些类型的微不足道的变化更加繁琐。

答案 2 :(得分:4)

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

  

如果 A B 更改而必须更改, A B 紧密耦合。< / p>

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

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

另一方面,你认为打字和耦合是相关的。特别是,更强和更静态的打字往往会增加耦合。例如,在动态语言中,您有时可以将字符串替换为数组,这取决于字符串可以被视为字符数组的概念。在Java中你不能,因为数组和字符串是不相关的。这意味着如果B用于返回一个数组并且现在返回一个字符串,那么它肯定会破坏它的客户端(只是一个简单的人为例子,但你可以提出更多更复杂和更引人注目的例子)。因此,更强的打字和更多的静态打字都是权衡取舍。虽然更强的打字通常被认为是好的,但是偏向静态与动态打字在很大程度上取决于上下文和个人品味:如果你想要一场好的斗争,尝试在Python程序员和Java程序员之间进行辩论。

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

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

答案 3 :(得分:2)

强类型是好的,因为它通过抛出编译时错误而不是运行时错误来防止难以发现错误。

紧密耦合的代码很糟糕,因为当你认为自己“知道自己需要实现什么”时,你经常会犯错,或者你还不知道你需要知道的一切。

即。您可能稍后发现您已经完成的任务可以在代码的另一部分中使用。那么也许你决定紧密地结合相同代码的2个不同版本。然后你必须对业务规则稍作修改,你必须改变两组不同的紧密耦合代码,也许你会得到正确的代码,最多只需要你两倍......或者最差你会在一个中引入一个错误,但不会在另一个中引入错误,并且它会在一段时间内未被发现,然后你发现自己处于一个真正的泡菜中。

或许您的业务增长速度远远超出预期,并且您需要将一些数据库组件卸载到负载平衡系统,因此现在您必须重新设计与现有数据库系统紧密耦合的所有内容以使用新系统。

简而言之,松散耦合使软件更容易扩展,维护和适应不断变化的条件和要求。

  编辑:我觉得我的解释   疏松耦合关闭或其他   读错了路。强大   和我联系就是上课的时候   引用的具体实例   另一堂课。松耦合就是在什么时候   一个类引用一个接口   另一个班可以实现。

     

我的问题是为什么不呢   特别称之为具体   一个类的实例/定义?一世   特别地将其类比   定义您需要的变量类型。   我一直在做一些阅读   依赖注入,他们似乎   把它当成松散的事实   耦合更好的设计。

我不确定你的困惑在这里。例如,假设您有一个大量使用数据库的应用程序。您有100个不同的应用程序需要进行数据库查询。现在,您可以在100个不同的位置使用MySQL ++,或者您可以创建一个调用MySQL ++的独立接口,并在100个不同的位置引用该接口。

现在您的客户说他想使用SQL Server而不是MySQL。

您认为哪种情况会更容易适应?在100个不同的地方重写代码,或者在1个地方重写代码?

好的......现在你说可能在100个不同的地方重写它并不是那么糟糕。

所以......现在你的客户说他需要在某些地方使用MySQL,在其他地方使用SQL Server,在其他地方使用Oracle。

现在你做什么?

在松散耦合的世界中,您可以拥有3个独立的数据库组件,这些组件都使用不同的实现共享相同的接口。在一个紧密耦合的世界中,你有100套开关语句,散布着3种不同的复杂程度。

答案 4 :(得分:1)

  

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

简短回答:您几乎从不知道完全您需要实现的目标。需求发生变化,如果您的代码首先松散耦合,那么适应性就不会是一场噩梦。

答案 5 :(得分:1)

  

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

我认为强力打字是好的还是鼓励是不公平的。当然很多人更喜欢强类型语言,因为它带有编译时检查。但很多人会说弱打字很好。听起来好像你听说“强”是好的,怎么能“松散”也好。语言输入系统的优点甚至不属于与类设计类似的概念。

旁注:don't confuse strong and static typing

答案 6 :(得分:1)

强类型将有助于减少错误,同时通常有助于提高性能。代码生成工具可以收集的关于变量可接受的值范围的信息越多,这些工具就可以用来生成快速代码。

当与类型推断和特征(如tral(perl6和其他)或类型类(haskell))结合使用时,强类型代码可以继续紧凑和优雅。

答案 7 :(得分:0)

如果在我们的函数中进行的任何修改(在派生类中)将更改基本抽象类中的代码,那么这将显示完全依赖性,这意味着它是紧耦合的。

如果我们不再编写或重新编译代码,那么它会显示较少的依赖关系,因此它是松耦合的。

答案 8 :(得分:0)

我认为紧密/松散耦合(对我来说:接口声明和对象实例的赋值)与Liskov Principle有关。使用松耦合可以实现Liskov原理的一些优点。

但是,只要执行了instanceof,强制转换或复制操作,松散耦合的使用就开始变得有问题了。此外,对于带有方法或块的局部变量,它是无意义的。