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

Language agnostic 如何使代码与不同的库版本兼容,以便能够在不同的环境中运行?,language-agnostic,Language Agnostic,我正在开发一个SQL工具来提取和显示Hadoop生态系统中的数据。我使用Spark和Hive库实现SQL连接和浏览 我正在使用一些API、类,它们是我从Spark和Hive及其内部方法扩展而来的。现在,许多API、类构造函数和方法语法都发生了变化 我需要在代码中找到一些方法来处理Spark和Hive库的多个版本,以便能够支持多种版本的Spark和Hive及其组合 在我的工具中,我必须扩展许多Spark SQL类并编写自己的实现。为了支持Spark的多个版本,我目前使用反射来实现Spark方法/A

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

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

我需要在代码中找到一些方法来处理Spark和Hive库的多个版本,以便能够支持多种版本的Spark和Hive及其组合

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

例如: 假设ThriftBinaryCLIServive是我扩展的一个类。 在Hive1.2和Hive2.1中,构造函数已更改。 在Hive1.2中,ThriftBinaryCLIServive(CLIService CLIService) 在Hive2.1中,ThriftBinaryCliserve(ClisService ClisService,Runnable oomHook)

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

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

我还尝试了一种自定义类加载器方法,其中我使用了两个不同的类加载器来加载不同版本的类,但没有多大帮助,而且从长远来看,这种方法不易管理,也很难调试


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

您可以使用adapter
设计模式来解决这个问题。每当使用不同的API引入新版本时,您只需引入一个新的
适配器
,它将现有代码的调用直接指向新的API。

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

如果不可能,请将您自己的代码拆分为一个部分,该部分取决于库的版本,而另一部分则不取决于库的版本。如有必要,让版本相关库实现一个Facade,该Facade将库的各种API转换为其他代码使用的公共内部API

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


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

您是否需要在单个版本或库中支持Spark/Hive的多个版本?我会发布带有独立Spark/Hive版本支持的独立版本,以消除复杂性不一定,但我希望避免为多个版本创建多个JAR,因为即使在Spark或Hive的微小版本更改中,各种方法语法也发生了更改。明白了,打破了更改(例如语法)在小版本中,更新是不好的做法(顺便说一句)