I am building an API which I intend to upgrade over time. Is it ever reasonable to include a version number as an argument in the API?
I'm writing a key/value store API in Ruby, Java, Erlang, and C#. I want to build something that is 开发者_运维技巧extensible as I know there are many things I have not thought of yet that may have to be incorporated in the future. However, I want to know if there is a clean way of doing this and whether version numbers play a part in this too.
You can do it, it's better (IMHO) if you just make your API backwards-compatible though. It's generally easier, as you don't need to branch on your side, based on the version number, you just re-implement the given method.
I suppose it's really quite implementation-specific (and also environment-specific). I'd do whatever seems easiest/better.
I'd say as long as your maintaining backwards compatibility in some fashion, then it's all good.
That could be reasonable if you're building an object oriented API and you give the version number to a factory. It's common in dynamic data centric APIs as well - you ask the library for data and have to indicate what format/version you want the data back as.
More commonly for "traditional" libraries(as in the ones you link to in your C/C++/.NET applications) done is:
provide an API to fetch the version number of the library. This allows the application to decide if it needs a newer/older version of the library.
be backwards compatible as long as you can.
Add functions, don't change them. If you have to add arguments/input or change behavior - create a new function rather, and keep the old one around.
when you eventually have to break backwards compatibility and get rid of all the old cruft kept around only for the sake of being backwards compatible, have a sane version scheme that clearly indicates incompatible versions.
I've used several APIs that support some kind of versioning, most notably ODBC. None of these allowed versioning at the API call level - they all required you to tell the library which version you wanted to work with on an one-off basis - something like:
MyAPI::UseVesion( 2, 1 );
Personally, I would avoid this path if at all possible (make your new APIs backwards compatible) and for sure versioning at the individual call level would be intolerable and unworkable. Imagine code like:
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
You can't detect the mismatch at compile time, and it may or may not work at run time. Yechh!
Firstly, what type of API are you meaning - a library that applications link against, or an XML/RPC API? I'm going to assume the latter in my answer.
Definitely - it's the only way that your API and/or the client can distinguish which methods/parameters are available to them. It also allows you to continue serving old clients with a new version of the API.
Something I've found works well in the past, is to have some form of handshake method, where the client tells the server which version it is expecting. The server then responds with its current version, and can optionally decide to not support that client (allowing you to phase out an older version, then stop supporting it further down the line, requiring clients to have been updated.)
As for a library, you should definitely include a version number so that applications can link against different versions, and can continue using an older version even if a newer one exists until the application has been upgraded to handle the new version.
Firstly, it's hard to be specific without knowing what language your API is for.
I think it would be acceptable to allow a version number on the creation of an Object. So that you could create a version 1 or version 2 MyApi
object, with different versions of the Object having different methods. It should still be possible to create version 1 obejcts with the version 2 API so users of the library can upgrade gradually.
I don't think you should version numbers on methods or function calls. To me this seem like adding boilerplate to every single call to your API. In this case consider using either optional parameters so you can extend without breaking backwards compatibility and deprecating methods where necessary.
Yes, allowing version numbers in APIs is reasonable but I would limit passing them to a single method in a MetaAPI, by which the user of your API retrieves a particular version of it.
For each version use a different interface and never change it once it has been released.
This makes backwards compatibility much easier.
Yes, take for example Google Maps:
<script type="text/javascript">
google.load("maps", "2");
</script>
Yep it is very sensible, especially if you are using a system built on marshalling / unmarshalling and interfaces (COM / CORBA / SOAP). It is even useful in monolithic applications.
However this approach is suited for very complicated software projects, and if you don't need it, don't use it -- you can get yourself entrenched in a never-ending version-hell.
edit: You might want to look at Apache Thrift (sparsely documented) for data interchange, or Protocol Buffers (less languages supported)
One thing you'll want to do is provide functions that take version numbers and make sense of them. Functions like:
def has_extended_key_format(version):
return version > 3
or:
#define HAS_EXTENDED_KEY_FORMAT(version) ((version) > 3)
(Yes, use #define
for C and C++, so the preprocessor can do things based on version at compile time.)
This way, your code is not loaded with Magic Numbers in your version checks, and people can read your code and know what feature you're really checking for.
精彩评论