为什么所有领先的开源Java库的包之间都有循环依赖关系?

为什么所有领先的开源Java库的包之间都有循环依赖关系?,java,spring,dependencies,package,circular-dependency,Java,Spring,Dependencies,Package,Circular Dependency,在过去的几周里,我一直在研究Java包结构和依赖模式。关于这个主题的文章中的一个常见线索是一条简单的规则,即包依赖项应该形成一个(DAG)。作者Robert Martin甚至将(ADP)形式化,其中指出 包之间的依赖关系结构必须是有向无环图(DAG)。也就是说,依赖关系结构中不能有循环 一些Java库确实遵守这个简单的规则。即,库(SpringCore、SpringWeb等)和 然而,令我惊讶的是,大多数领先的开源Java项目并没有做到这一点 以下开源项目在包之间具有循环依赖关系: Netfl

在过去的几周里,我一直在研究Java包结构和依赖模式。关于这个主题的文章中的一个常见线索是一条简单的规则,即包依赖项应该形成一个(DAG)。作者Robert Martin甚至将(ADP)形式化,其中指出

包之间的依赖关系结构必须是有向无环图(DAG)。也就是说,依赖关系结构中不能有循环

一些Java库确实遵守这个简单的规则。即,库(SpringCore、SpringWeb等)和

然而,令我惊讶的是,大多数领先的开源Java项目并没有做到这一点

以下开源项目在包之间具有循环依赖关系:

  • Netflix Hystrix(每个包都是一个周期的一部分!)
  • AWS SDK
  • 公地郎
  • 公地收藏
  • 匕首
  • 谷歌Gson
  • 谷歌用户界面
  • 冬眠甲虫
  • 休眠验证器
  • 杰克逊核心
  • 乔达时间
  • 游戏框架
  • 朱尼特
  • 倒退
  • 码头
  • AspectJ
  • 内蒂
  • java.util
  • java.lang
我是否误解了软件工程原理?或者开发人员是否会低估这种包组织技术

参考资料:
  • 弹簧芯4.2.3[]
  • 谷歌番石榴
  • Hystrix[][]
  • java.util[][]

我可以确认,在使用分析了许多java项目后,其中许多项目包含包之间的循环依赖关系,原因是许多项目选择“按功能包”而不是“按层包”的方法

下面是一个关于这两种方法之间区别的讨论

让我们以JDK中的一些包为例


这些包是按功能设计的,regex功能分组在java.util.regex包中,它需要java.security包中的一些安全功能,安全类也需要一些regex功能

您是如何得出这些API中存在循环依赖而不是Spring的结论的?简单分析导入!就这些!(我问这个是因为我想知道你是否使用过任何工具)。你能举一个简单的例子吗,例如在
java.lang
中?是的,我将附加一些图像和图形文件…如果你计划将其中一个包作为一个自包含的库发布,这个“规则”很有用,这是一个良好组织的标志,但实际上,包之间的循环依赖性并不是一个真正的问题,避免它们可能是一项艰巨的任务,除了遵守规则的良好感觉之外,没有任何具体的好处。你是如何得出这个理论的?按功能打包不能保证或导致循环依赖。看看spring core]]或guava]]就知道了。并非所有“按功能打包”设计的项目都有循环依赖关系,但当您决定按功能分组时,第一个目标不是要有分层的代码(按层打包方法)。在许多情况下,一种功能可以使用另一种功能,反之亦然。