【问题标题】:Should I be concerned with large number of dependencies?我应该关心大量依赖项吗?
【发布时间】:2010-12-14 02:36:38
【问题描述】:

我正要在项目中包含HtmlUnit 库。我解压了 zip 文件,发现它不少于 12 dependencies。

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

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

我应该担心这个吗?在这种情况下,最佳做法是什么?

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

【问题讨论】:

  • “关于重新发明轮子的事情是……你会得到一个圆形的轮子。”

标签: java dependencies libraries


【解决方案1】:

小心处理您的依赖关系。它们可以为您带来更快的速度,但在路上保持下去可能会很痛苦。以下是我的想法:

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

【讨论】:

  • +1 查看社区如何支持旧版本的库。
  • 使用 LGPL 许可库非常适合闭源公司环境。然而,许多律师并不理解这一点。令人沮丧。
  • 我不是层,但据我了解,问题在于库的升级条款(在二进制兼容时以次要版本的方式)。作为软件供应商,我们必须允许用户升级库并且仍然兼容。如果我们不遵守这一点,我们将违反许可条款,这可能是分发软件时的一大难题。
  • 您的软件是否会禁止用户将库的升级版本放入 lib 文件夹?让他们这样做会有什么问题?许可证不会强迫您提供一种简单的方法来做到这一点,对吗?或者强迫你创建一个新的安装程序?我可以理解如何更容易完全避免这个问题。
【解决方案2】:

如果没有一个活跃的社区来长期维护这些库,这可能是一个严重的问题。可以使用库,但老实说,您应该注意获取源代码并将它们放入您的 VCS。

【讨论】:

  • 啊,是的,我为一个 Android 项目做过一次。丑陋,但它的工作原理。尽管如此,它并没有解决依赖冲突的问题......
  • @aioobe 如果一个项目不再维护,它至少会给你一个改变来解决你依赖的少数方法的问题。
【解决方案3】:

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

一般来说,这样做可能是个好主意。但是,您上游和下游的每个人都应该如此。

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

最后(也是最重要的,实际上是我最关心的问题):如果我想包含另一个依赖于与该库相同的库但版本不同的库怎么办?也就是说,如果 HtmlUnit 依赖于一个版本的 xalan 而我需要的另一个库依赖于不同版本的 xalan,该怎么办?

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

我应该担心这个吗?

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

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

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

Maven 还消除了创建发行版的需要。您只需将 您的 工件与 references 发布给它们的依赖项。然后,Maven 命令会从发布的任何地方下载相关工件。

编辑

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

【讨论】:

  • 谢谢,+1。但实际上,我打算使用 HtmlUnit 进行一些基本的屏幕抓取。也许不是它的用途,但我喜欢它提供的界面。
  • 和@aioobe -- HtmlUnit 是最灵活、最完整、最易于使用的基于 Java 的网页交互自动化工具之一。尽管有它的名字,但它经常在“测试”阶段范围之外使用,并作为“运行时”功能的一部分。
【解决方案4】:

其实我也发生过类似的事情。

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

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

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

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

它丑吗 - 是的(糟糕!),但它有效。

【讨论】:

    【解决方案5】:

    我尽量避免引入无意义的依赖,因为可能会遇到冲突。

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

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

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

    至于安全问题——您可能会权衡广泛使用的库出现问题的可能性,与您的手写的未经测试的代码存在一些安全漏洞的可能性。不过,归根结底,您要对程序的安全性负责——所以做您认为必须做的事情。

    【讨论】:

    • 啊,好点,从没想过。不同的包(如果允许)名称应该可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    • 2010-09-18
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多