如何让代码兼容不同的库版本,才能在不同的环境下运行?

How to make code compatible with different library version to be able to run on different environments?

我正在开发一个 SQL 工具来从 Hadoop 生态系统中提取和显示数据。我已经使用 Spark 和 Hive 库来实现 SQL 连接和浏览。

我正在使用一些 API,classes,我从 Spark 和 Hive 及其内部方法扩展而来。现在许多 API 和 Class 构造函数和方法语法都发生了变化。

我需要通过某种方式在我的代码中处理多个版本的 Spark 和 Hive 库,以便我可以支持各种版本的 Spark 和 Hive 及其组合。

在我的工具中,我必须扩展许多 class 的 Spark SQL 并编写我自己的实现。为了支持多个版本的 Spark,我目前使用反射来实现 Spark method/APIs 调用兼容性。

示例: 假设 ThriftBinaryCLIServive 是我扩展的 class。 在 Hive1.2 和 Hive2.1 中构造函数发生了变化。 Hive1.2中,ThriftBinaryCLIServive(CLIService cliService) 在 Hive2.1 中,ThriftBinaryCLIServive(CLIService cliService, Runnable oomHook)

解决这个问题 我写了一个单独的扩展版本 classes 说: CustomThriftBinaryCLIServive1_2(与 Hive 1.2 兼容)和 CustomThriftBinaryCLIServive2_1(与 Hive 2.1 兼容)并将它们放在不同的源文件夹中。 我使用 Maven 一次编译特定源文件夹中的包。 我使用反射在 运行 时间根据 Hive 版本实例化适当的 class 并使用 ThriftBinaryCLIServive 作为参考 class.

目前,这种方法对我有效。但我看到未来代码可维护性问题和代码重复在某种程度上,我不确定这是否是正确的方法。

我也尝试过自定义 Class 加载器方法,我使用两个不同的 class 加载器来加载不同版本的 class 但没有太大帮助,而且事实并非如此长 运行 易于管理,也难以调试。

有人可以提出其他更好的方法来解决这个问题吗?

为此,您可以使用适配器 design pattern。每当引入具有不同 API 的新版本时,您只需引入一个新的 Adapter,它将直接从现有代码调用新的 API.

编程到最小公分母。如果版本 1 提供功能 A,而版本 2 提供功能 A 和 B,则在您的代码中您可以使用功能 A 但不能使用功能 B。

在不可能的情况下,将您自己的代码拆分为取决于库版本的部分和不依赖库版本的部分。如有必要,让依赖于版本的库实现一个外观,将库的变化 API 转换为您的其他代码使用的通用内部 API。

使用可轻松进行分支开发的现代版本控制系统。接受您必须同时处理不同版本的代码,在分支之间合并(针对不同版本)。从旧版本合并到新版本通常效果更好。

接受您不能永远支持旧版本的事实。正如库的旧版本变得过时且不再受支持一样,旧版本的代码也必须如此。