【问题标题】:Is circular dependency good or bad [closed]循环依赖是好是坏[关闭]
【发布时间】:2014-11-07 15:41:19
【问题描述】:

我需要知道为什么我们需要避免循环依赖? 如果我们认为,在现实世界中,循环依赖非常重要。就像一个朋友需要另一个朋友的东西,另一个需要这个朋友的东西,所以它是一种循环,对吗?

那么为什么循环依赖是一个糟糕的设计呢? 如果我们真的需要避免这种情况,那么对于这种情况,面向对象世界中最好的设计是什么?

【问题讨论】:

  • 根据我的经验,循环引用的主要问题是内存管理——谁拥有什么?
  • 它既不好也不坏:就是这样。如果觉得必须,请注意内存泄漏。
  • 上次我检查(也就是我必须编译它)llvm 项目全部用于循环依赖,他们正在编写一个虚拟机/编译器。您可以以此为例,也许会问他们为什么要采用这种设计。
  • 让我们以头文件为例:头文件A需要头文件B中的东西才能工作,而头文件B需要头文件A中的东西才能工作。但是头文件B不能包含头文件A,因为头文件A需要先包含B,而B首先需要包含A,以此类推。这是一个典型的循环依赖,在 C 和类似语言的初学者中很常见。
  • 你的例子“......一个朋友需要其他朋友的东西,另一个需要这个朋友的东西......”不是依赖,除非第一个朋友不能做第二个需要的东西,除非他们提供第一个朋友需要的东西。在没有依赖关系的情况下,任何一方都可以随时为另一方提供服务。因此,通常,您希望避免循环依赖。

标签: c++ c circular-dependency


【解决方案1】:

循环依赖的问题很像鸡和蛋的问题。

如果你依赖我设置,而我依赖你设置,我们该如何开始?

这样的必然结果是我们如何结束 - 如果我引用了你的资源而你引用了我的资源,我永远无法清理,因为那会破坏你,而你无法清理,因为那会破坏我.

这两种情况的答案都是引入一个中间人,将其中一方的依赖传递给他,所以如果你将资源传递给中间人,你将依赖我和中间人,而我将依赖中间人。因此你可以清理,因为你现在没有资源,我可以清理,因为没有人依赖我,然后中间人可以清理。

【讨论】:

  • 很好的通用答案,避免了语言特定的 do-hickies 的陷阱,这些陷阱可能会处理部分复杂性,并且在我知道的所有情况下都是有用的模式。 +1
  • 嗯,谢谢 gbjbaanb。但这也意味着在虚拟世界中,两个朋友不能直接互动,他们需要一个中间人来做到这一点
  • 你们仍然可以交流,只是不能依赖。因此,一旦您进行了这样的设置,您必须期望合作伙伴不在场。紧耦合在循环依赖中很重要。
  • @Nipun:友谊不是循环依赖。如果我需要等待我的朋友与我互动才能与他们互动,而他们必须等待我开始互动,那将是循环依赖,但友谊不会那样运作。
  • The problem with circular dependencies is rather like the chicken and egg problem 我不喜欢这句话,听起来我们没有图表,只有树可供我们使用;声明和定义之间也有区别,除了循环 dep 之外,我不能代表所有语言。通常是相对于声明而不是定义的时间,对于任何现代编译器,这个问题不仅与此相当,而且 100% 可解决。例如转发声明可以解决 circ。部问题,就这么简单。
【解决方案2】:

您需要意识到循环依赖意味着您只能一起使用相应的循环依赖类:如果在AB 之间存在循环依赖,则不能使用A 或@ 987654324@ 在任何程序中独立。坚持你的问题:当然,你不需要另外两个朋友存在!您所需要的只是某种方式来引用某些人并以一种可能受限于他们的实际能力的方式与他们互动。

但是,通常可以让类的对象相互使用而不会导致循环依赖。为此,重要的是要确定实际上是什么导致了两个类/组件之间的依赖关系(它们并不完全等价,但提供完整的定义会有些冗长)。 A 在这些条件下依赖于 B

  1. A 包含B 类型的成员时。
  2. A 派生自B 类型时。
  3. A 使用B 类型的值作为函数签名的一部分时。
  4. A 在其实现中使用B
  5. 我可能在这里忘记了一些东西(我记得有更多的原因将类耦合在一起)。

当两个类之间存在循环依赖关系时,可能有办法打破这种依赖关系。通常,可以通过将两个类中的一个拆分为基类和派生类来打破依赖关系,而基类不依赖于另一个类。还有许多其他方法可以打破依赖循环。 John Lakos 的“Large Scale C++”(1996 年)基本上都是关于打破依赖循环并激发循环依赖为何不好(我猜,他不同意这种简化的描述)。

...而且,是的,循环依赖不好的:

  1. 它们会导致程序包含不必要的功能,因为不需要的东西被拖入其中。
  2. 它们使测试软件变得更加困难。
  3. 它们使对软件的推理变得更加困难。
  4. 它们使更换系统部件变得更加困难。
  5. ...可能还有其他一些原因。

以上内容是从 C++ 的角度制定的。循环依赖的一些原因在 C 中可能[直接] 不存在,但相同的概念也大致适用于 C。

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    • 2011-05-04
    相关资源
    最近更新 更多