我正在构建一个我打算随着时间的推移升级的API。在API中包含版本号作为参数是否合理?
我正在用Ruby,Java,Erlang和C#编写一个键/值存储API。我想构建一些可扩展的东西,因为我知道有很多我还没有想到的东西可能必须在未来被合并。但是,我想知道是否有一种干净的方式来执行此操作以及版本号是否也参与其中。
答案 0 :(得分:7)
你可以做到这一点,如果你只是让你的API向后兼容,那就更好了(恕我直言)。它通常更容易,因为您不需要根据版本号分支,只需重新实现给定的方法。
我认为它确实非常特定于实现(以及特定于环境)。我会做最简单/更好的事情。
我会说,只要你保持某种时尚的向后兼容性,那就一切都很好。
答案 1 :(得分:5)
如果您正在构建面向对象的API并且将版本号提供给工厂,那么这可能是合理的。 它在动态数据中心API中也很常见 - 你向库询问数据,并且必须指出你想要数据的格式/版本。
更常见的是“传统”库(如在C / C ++ / .NET应用程序中链接到的那些库)完成的是:
提供API以获取库的版本号。这允许应用程序决定是否需要更新/更旧版本的库。
只要你可以向后兼容。
添加功能,不要更改它们。如果你必须添加参数/输入或更改行为 - 请创建一个新函数,并保留旧函数。
当你最终必须打破向后兼容性并且为了向后兼容而摆脱所有旧的残存时,有一个明智的版本方案,清楚地表明不兼容的版本。
答案 2 :(得分:5)
我使用了几种支持某种版本控制的API,最着名的是ODBC。这些都不允许在API调用级别进行版本控制 - 它们都要求您在一次性基础上告诉库您要使用哪个版本 - 例如:
MyAPI::UseVesion( 2, 1 );
就个人而言,如果可能的话,我会避免使用这条路径(使新的API向后兼容),并确保在单个呼叫级别进行版本控制是不可容忍的,也是不可行的。想象一下代码:
MyAPI::Handle h = MyAPI::GeHandle( 2, 1 ); // get 2.1 version of handle
MyAPI::UseHandle( 3, 0, h ); // use it somehow with a 3.0 function
您无法在编译时检测到不匹配,并且在运行时可能会或可能不会。 Yechh!
答案 3 :(得分:3)
首先,您的意思是什么类型的API - 应用程序链接的库或XML / RPC API?我将在答案中假设后者。
绝对 - 这是您的API和/或客户端可以区分哪些方法/参数可用的唯一方式。它还允许您继续使用新版本的API为旧客户提供服务。
我发现过去运行良好的东西,就是采用某种形式的握手方法,客户端告诉服务器它正在期待哪个版本。然后服务器以其当前版本进行响应,并且可以选择不支持该客户端(允许您淘汰旧版本,然后停止支持它进一步下线,要求客户端已更新。)
对于库,您应该明确包含版本号,以便应用程序可以链接到不同的版本,并且可以继续使用旧版本,即使存在较新的版本,直到应用程序已升级为处理新版本。 / p>
答案 4 :(得分:3)
首先,如果不知道您的API是什么语言,很难具体说明。
我认为在创建Object时允许版本号是可以接受的。这样您就可以创建版本1或版本2 MyApi
对象,而不同版本的Object具有不同的方法。仍然可以使用版本2 API创建版本1对象,以便库的用户可以逐步升级。
我认为你不应该在方法或函数调用上版本号。对我来说,这似乎是为每次调用API添加样板文件。在这种情况下,请考虑使用可选参数,以便在不破坏向后兼容性的情况下进行扩展,并在必要时弃用方法。
答案 5 :(得分:3)
是的,在API中允许版本号是合理的,但我会限制将它们传递给MetaAPI中的单个方法,API的用户通过该方法检索它的特定版本。
对于每个版本,使用不同的界面,一旦发布,就不要更改它。
这使得向后兼容性变得更加容易。
答案 6 :(得分:2)
是的,例如Google Maps:
<script type="text/javascript">
google.load("maps", "2");
</script>
答案 7 :(得分:2)
是的,这是非常明智的,特别是如果您使用的是基于编组/解组和接口(COM / CORBA / SOAP)的系统。它甚至可用于单片应用程序。
然而,这种方法适用于非常复杂的软件项目,如果你不需要它,就不要使用它 - 你可以让自己陷入一个永无止境的版本 - 地狱。
编辑:您可能希望查看Apache Thrift(稀疏文档)进行数据交换,或Protocol Buffers(支持的语言较少)
答案 8 :(得分:1)
您要做的一件事是提供获取版本号并理解它们的功能。功能如:
def has_extended_key_format(version):
return version > 3
或:
#define HAS_EXTENDED_KEY_FORMAT(version) ((version) > 3)
(是的,对{C和C ++'使用#define
,因此预处理器可以在编译时根据版本执行操作。)
这样,您的代码在版本检查中未加载Magic Numbers,人们可以阅读您的代码并了解您真正要检查的功能。