我应该关注大量依赖吗?

时间:2010-12-11 22:39:24

标签: java dependencies libraries

我正准备将HtmlUnit库包含在项目中。我解压缩了zip文件并意识到它不低于12 dependencies

在引入依赖项时,我一直很关心。我想我必须将所有这些依赖项与应用程序一起发送(在这种特殊情况下为8.7 MB)。我是否应该费心检查这些库的安全更新?最后(最重要的是,实际上我最关心的是):如果我想要包含另一个库,该库依赖于与此库相同的库,但具有不同的版本,该怎么办?也就是说,如果例如HtmlUnit依赖于xalan的一个版本和我需要的另一个库,取决于不同版本的xalan会怎样?

HtmlUnit为我解决的任务可以“手动”解决,但这可能不会那么优雅。

我应该关注这件事吗?这些情况下的最佳做法是什么?

编辑:我对一般情况感兴趣,而不是特别涉及HtmlUnit。我只是在这里用它作为一个例子,因为那是我目前关心的问题。

5 个答案:

答案 0 :(得分:6)

小心处理您的依赖项。它们可以为您带来更多的速度,但是可能是一种难以维持的道路。以下是我的想法:

  • 使用某些软件来维护您的依赖项。 Maven是我用来做Java的。没有它,你很快就会忘记你的依赖。
  • 请记住,各种库具有不同的许可证。未授予给定许可证适用于您的设置。我在软件公司工作,我们不能在我们发布的任何软件中使用基于GPL的库,因为我们销售的软件是封闭源代码。同样我们也应该避免使用LGPL(这是由于一些错综复杂的律师推理,不要问我为什么)
  • 对于单元测试我会说全力以赴。如果您将来必须重写测试,那么这不是世界末日。甚至可能是那部分软件要么非常稳定,要么甚至不能再维护。放弃这些并不是什么大不了的事情,因为当你得到它时你已经获得了巨大的增长速度。
  • 有些库比其他库更难以替换。有些像婚姻应该持续软件的生命,但其他一些只是易于更换的工具。 (Think Spring与xml库相比)
  • 查看社区如何支持旧版本的库。他们支持旧版本吗?当生命继续而你被困在一个版本时会发生什么?是否有活跃的社区,或者您是否有自己维护它的技能?
  • 您的软件应该持续多久?是一年,五年,十年还是一年?如果软件的时间跨度很短,那么您可以使用更多的软件来获取目标,因为能够跟上升级库并不重要。

答案 1 :(得分:2)

  

我是否应该费心检查这些库的安全更新?

一般来说,这样做可能是个好主意。但那么你们上游和下游的所有人都应如此。

在您的特定情况下,我们正在讨论测试代码。如果仅在测试中使用的库中的潜在安全漏洞很严重,那么您的下游用户正在做一些奇怪的事情......

  

最后(最重要的是,实际上我最关心的是):如果我想要包含另一个库,该库依赖于与此库相同的库,但具有不同的版本,该怎么办?也就是说,如果例如HtmlUnit依赖于一个版本的xalan和我需要的另一个库,取决于不同版本的xalan会怎样?

啊,是的。假设您手动构建自己的类路径等,则需要决定应该使用哪个版本的依赖库。选择最新使用的版本通常是安全的。但是如果旧版本没有向后兼容新版本(对于您的用例)那么您就遇到了问题。

  

我应该关注这件事吗?

IMO,对于您的特定示例(我们在谈论测试代码),没有。

  

在这些情况下,最佳做法是什么?

使用Maven!它明确地将依赖关系暴露给下载代码的人,使他们能够处理问题。它还会告诉您何时遇到依赖项版本冲突,并提供一个简单的“排除”机制来处理它。

Maven也不需要创建发行版。您只需将带有引用 工件发布到其依赖项。然后,Maven命令从发布的任何地方下载依赖的工件。

修改

显然,如果您将HtmlUnit用于生产代码(而不仅仅是测试),那么您需要更加关注安全问题。

答案 2 :(得分:2)

如果没有活跃的社区长期维护图书馆,这可能是一个严重的问题。可以使用库,但说实话,您应该关心获取源并将它们放入VCS中。

答案 3 :(得分:1)

实际上我发生了类似的事情。

我的两个依赖项具有相同的“传递”依赖关系,但版本不同。

我最喜欢的解决方案是通过不包含太多依赖项来避免“依赖性蠕变”。因此,最简单的解决方案是删除我需要的那个,或者用一个简单的Util类替换的那个,等等。

太糟糕了,并不总是这么简单。在您实际需要两个库的不幸情况下,可以尝试同步它们的版本,即降级其中一个版本以使依赖版本匹配。

在我的特殊情况下,我手动编辑了其中一个jar,从中删除了较旧的依赖项,并希望它仍然适用于从其他jar加载的新版本。幸运的是,它做到了(即传递依赖的维护者没有删除库使用的任何类或方法)。

难看 - 是的(哎呀!),但它确实有效。

答案 4 :(得分:1)

我尽量避免引入无聊的依赖关系,因为它可能会遇到冲突。

我见过的一个有趣的技术用于避免冲突:重命名库的包(如果它的许可允许你 - 大多数BSD风格的许可证。)我最喜欢的例子是Sun在将Xerces构建到JRE作为事实上的JAXP XML解析器:他们将整个Xerces从org.apache.xerces重命名为com.sun.org.apache.xerces.internal。这种技术是否剧烈,耗时且难以维护?是。但是它完成了工作,我认为这是一个重要的可能替代方案。

另一种可能性是 - 遵守许可条款 - 从库中复制/重命名单个类甚至单个方法。

不过,

HtmlUnit可以做很多。如果你真的在很多不同的输入数据上使用它的大部分功能,那么就很难花费大量时间从头开始重新编写功能或重新打包它。

至于安全问题 - 您可能会权衡广泛使用的库存在问题的可能性,以及您手写的测试较少的代码存在某些安全漏洞的可能性。最终,你对你的程序的安全性负责 - 所以做你认为必须的。