在不破坏兼容性的情况下合并两个 Python API

Merging two Python APIs without breaking compatability

场景如下:

存储系统 A (Java) 是默认设置,并且具有 Python API API_A。最近引入了存储系统 B (Java/C++),但没有 Python API。人们 "somehow" 让 BAPI_A 一起工作,但它非常慢,尤其是随着规模的增加。因为,这是 Python API 的唯一选择,现在很多代码都依赖 API_AB 交互。

来自存储系统 B 的团队现在有 Python API、API_BAPI_B 显然更有效率。但是,API_AAPI_B 之间有很多差异。例如,列表目录方法 return 具有完全不同字段的对象。 API_B 不允许递归删除目录,但 API_A 允许。等等...

问题:

在不破坏兼容性的情况下合并两个 API 的最佳方法是什么?特别是API_A已经在使用了,那么透明的把API_B集成进去的最好方法是什么?

我认为创建装饰器不会起作用,因为方法签名在 API 之间有所不同。 API_A 中有一些方法在 API_B 中不存在。 (提高 NotImplementedException 是这里唯一的选择)。

我能想到的唯一解决方案是天真的解决方案,我必须在 API_A:

中的每个函数中进行检查
if self.isStorageA:
    return method_of_A(args)
else:
    return method_of_B(args, args)

我正在寻找一种更好、更易于维护的方法来做到这一点。非常感谢任何帮助!

为 API B 编写一个“看起来像”API A

的包装器库

特别是,它必须提供具有完全相同签名的完全相同的方法。如果 API B 没有实现某些功能(如递归枚举),则包装器必须根据 API B 重新实现此功能。例如,您可以编写一个枚举当前目录的函数,然后每个子目录,以此类推递归地替换 API A 的本机功能。如果不可能做到这一点(也就是说,如果 API A 提供了一些功能而不能完全用 API B 完成),那么 API B 不是 API A 的合适替代品,你不应该继续你的计划。

您还应该为您的包装器编写一系列单元测试,以确保它的行为与 API A 在各种条件下的行为相同,特别是在边缘情况下。如果 A 已经有单元测试,那么就使用那些。

最后,一旦您确定包装纸与 A 没有区别,您就可以用包装纸替换 A。只需替换模块和包就足够简单了,但是如果由于某种原因这对您不起作用,您可以替换 sys.modules 中的 A 以确保 A 的导入得到包装器。