如何使代码与不同的库版本兼容以能够在不同的环境中运行?

时间:2019-01-10 06:59:08

标签: language-agnostic

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

我正在使用一些我从Spark和Hive及其使用的内部方法扩展的API,类。现在,许多API,类构造函数和方法语法已更改。

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

在我的工具中,我不得不扩展许多Spark SQL类并编写自己的实现。为了支持Spark的多个版本,我目前使用反射来实现Spark方法/ API的调用兼容性。

示例: 说ThriftBinaryCLIServive是我扩展的类。 构造函数已在Hive1.2和Hive2.1中进行了更改。 在Hive1.2中,ThriftBinaryCLIServive(CLIService cliService) 在Hive2.1中,ThriftBinaryCLIServive(CLIService cliService,Runnable oomHook)

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

当前,这种方法对我有用。但是我以后会看到代码可维护性问题,并且在某种程度上会重复代码,因此我不确定这是否是正确的方法。

我还尝试了一种“自定义类加载器”方法,该方法使用两个不同的类加载器来加载不同版本的类,但并没有太大帮助,而且长期运行起来也不易管理,也很难调试。

有人可以建议其他更好的方法来解决此问题吗?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

在不可能的地方,将您自己的代码分成取决于库版本的部分和不取决于库版本的部分。如有必要,请版本依赖的库实现Facade,该库将库的各种API转换为其他代码使用的通用内部API。

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

接受您永远无法支持旧版本的提示。正如旧版本的库已过时且不再受支持一样,旧版本的代码也必须如此。