类之间的循环依赖:它们为什么是坏的以及如何摆脱它们?

问题描述 投票:2回答:2

我觉得循环依赖(又称循环引用)意味着糟糕的设计并损害项目。我怎样才能说服我的队友和我的经理?

我的项目是依赖性混乱。有没有一种方法可以摆脱错误的依赖关系,然后保持清晰度?

design-patterns dependencies dependency-management circular-dependency
2个回答
6
投票

为什么循环依赖(CiD)不好?

两个原因:

  1. 可维护性。 您希望您的代码是分层的,即您希望有一个自上而下的依赖关系图(一个图表显示所有箭头向下,没有箭头向上)。如果您有CiD,则您的代码不是分层的。 为什么分层代码意味着可维护性?因为,每次更改类的界面时,都可以确保它下面的任何内容都不会受到影响。这些知识使系统的维护和开发更便宜且不易出错。 好消息是,使用Visual StudioEclipseNetBeansIntelliJ等现代开发工具,为项目生成图表相当容易。
  2. 可靠性。 您不希望在生产中出现意外的无限递归。例如,当您的配置想要记录错误并且您的错误记录器想要从配置中读取日志文件的名称时(您的测试将通过,因为测试环境中没有错误)。 (不幸的是,即使没有CiD,也可以开发出意想不到的递归。)

有没有好的CiD?

某些CiD有效,有用,并且不会影响可维护性或可靠性:字符串和对象,文件和文件夹,节点和边缘。通常,这样的圆圈位于一个包中,并且不会影响包之间的循环依赖性。

如何检测包CiD?

您可以在依赖关系图上直观地检测CiD(请参阅上面的生成工具的链接)。

如果您的项目很大或者您想要连续观察CiD,那么实现一个使用反射来检测CiD的工具很简单(遍历类或包深度优先并在第一个返回参考处停止)。

注意,如果一个包在其他包中声明,这并不意味着它们相互依赖,除非它们的类相互引用。

我的项目是依赖性混乱。有没有一种方法来解决它?

dependency mess是的,有。以下是步骤:

  1. 设计所需的结构。 一个。创建现有包的简单列表,如下所示:enter image description here 如果您的包结构是分层的,请将其展平,并且不要忘记根包。 湾组织包。 重新排序列表,使具有较低抽象级别的包更接近底部,具有较高抽象级别的包更接近顶部。如果包中包含低和高抽象级别的类,您可能希望将此包打破为两个。 如果你有太多的包,首先将它们分成几层,订购层,然后在这些层内订购包。此步骤应该产生所需的包顺序,您希望依赖关系在哪里停止而不是向上。 C。以相同的方式组织包中的类。
  2. 使流程可衡量。 测量到所需结构的距离,以便在靠近目标时可以看到进度。对于每个类,计算错误依赖项的数量(指向的依赖项)。这些数字的总和将成为您的指标。最后,它将为零。 设置监视以检测新的错误依赖项。你想在他们即将检查另一个错误的依赖关系之前阻止你的队友(和你自己)。
  3. 逐个解决错误的依赖关系。通常,从下到上更容易,因为您首先要澄清基础知识。 这些提示可能有所帮助 A.你有一个“死亡之星”或“上帝对象”,即一个它所知道的类所知的对象。换句话说,这样的类是许多循环依赖的一部分,可能导致每个类的依赖性几乎所有其他课程。 解: 大多数死亡星可以通过将它们分成两个(或更多)类来解决,其中一个类只包含状态和非常基本的操作,另一个类包含高级操作(通常第二个类是静态的)。 enter image description here B.类之间没有一个圆圈,只是在包之间。 解: 考虑将一些类移动到其他包。 C.你有一个使用某些上层类方法的类,但它没有自己的实例化。 解: 使用回调接口或回调方法(模式Observer)。 enter image description here D.你有两个相互创造并使用彼此方法的类。 解决方案: 将类组合成一个类。 将类放入一个包中,并将它们的关系声明为一个好的CiD。 为其中一个类创建Factory类和接口。

enter image description here

如何在项目中保持清晰度?

如果你有一个小团队和一个小项目,只需向你的队友解释规则,偶尔检查图表。

如果项目很大且很复杂,那么每当有人编译或检查错误的依赖项时,您应该建立一个接收警报或拒绝的过程。


1
投票

首先,当您的项目如此简单时,没有反模式设计可能会产生问题,并且确实使事情变得更容易。它只会在项目变得复杂时出现问题。选择平衡点和右边是设计的一部分。说服某人总是需要一个真正的错误。

简而言之,要处理循环依赖关系,您总是需要将其与多任务分开。例如:enter image description here

原则是使每个单元专注于其核心业务或服务。如果你有一个圈子有时意味着你建立一个多核业务的单位。但实际上总是有更多的矿工周期,因为真正的业务流程就像这样。当它与单元的核心无关时,它是可以的。

顺便说一句,有人可以帮我内联图片吗?谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.