Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for API backwards compatibility

I'm working on an iPhone/iPad/Android app which communicates with a JSON API.

The first release of the version of the app is complete, and now additional phases of development are taking place. In the additional phases, the app needs to integrate with a new version of the API and allow the user access to additional features such as new screens or modified behaviour within existing screens. The app does however need to be backwards with previous versions of the API.

What is the best practice for tackling such a requirement? I could of could do checks throughout the code:

if (APIVersion == 1) {

} else if (APIVersion == 2) {

} else if (APIVersion == ....) {

}...

But I'm concerned about the scalability of this approach. The factory method comes to mind but I'm not sure how far this would get me.

Thanks, Mark

like image 590
Mark Avatar asked May 23 '12 08:05

Mark


People also ask

Which Microservice API changes is backwards compatible?

API backward compatibility In microservices systems, you need to make changes to service APIs in a backward compatible manner. A change to the API should not break existing consumers of the API.

What can be solved using backward compatibility?

Backward compatibility can be used to preserve older software that would have otherwise been lost when a manufacturer decides to stop supporting older hardware. Classic video games are a common example used when discussing the value of supporting older software.

What is Versionless API?

Versionless APIs is meant in the same way as Serverless. Serverless is not about "no servers". Serverless means, you don't have to deal with servers. Versionless means, you don't have to deal with versions.

What does API compatibility mean?

API compatibility exampleAn API is backward compatible if a client (a program written to consume the API) that can work with one version of the API can work the same way with future versions of the API.


2 Answers

Release of a new API version is a very rare thing. Usually you can achieve backward-compatibility just by adding new optional parameters or new methods. For example, if you had method named search, but now you are dissatisfied with the way it works, you may deal with it in various ways:

  • If the change is simple you may add a new mode parameter which defaults to mode1 (so it's backward-compatible). If user supplies mode2 you detect it with a proper if condition as you proposed yourself. (Also, usually you can think of a better name than "mode".)

  • If the change is a big one, you may add a new search2 service which uses the new interface. Then you mark search method as deprecated (but still working and backward-compatible). Usually when you do this, you can refactor your code in such a way, that almost all of the logic is inside the search2 method, and your old search method calls search2 internally with modified parameters (and re-formats the results appropriately). If you do this properly, you won't ever need to change search method anymore. When you alter your tables etc. - you will only need to modify search2.

My point is, avoid releasing N+1-st version of an API. Such big release implies major changes in ALL of your methods, not just one. Many major APIs never released version 2 of their API, they still use version 1, just slightly modify portions of it, as in the example above.

If you are absolutely sure about releasing N+1-st version of you API, create new entry points for ALL of your methods. If you had a folder named services, create new one named services-v2. Refactor your services code so that it uses the most of services-v2. If you think it's overkill, then I think you don't need N+1-st version of your API yet.

BTW, do not confuse centralized APIs (like Google Maps) with distributed ones (like Android). Android releases new API versions all the time, because there are billions of Android servers (each Android device is one), and they all cannot be simply upgraded remotely by Google. The next version of Android is still backward-compatible with the previous one, the number is increased only to indicate new features. E.g. You can still run apps built for Android 3.0 on Android 7.0 (the user might get some extra warnings, but the app will run). Android-app developers use these numbers in order to describe "minimum requirements" for their apps. Whereas, centralized APIs usually increase their version number to indicate a major backward-incompatible change.

like image 155
wrygiel Avatar answered Oct 07 '22 10:10

wrygiel


I guess you already have a separation of concerns. I mean, getting the datas for your app is only done through the Model (for example).

So you only have to change the model.

What I suggest is that there is only one entry point: the "router" file. This file checks the API version needed, and loads the correct file. This way, you get different files for each API. The "router" file won't be very big, and each new API version will have its own file, so you're not mixing everything.

For example, in the "router" file:

function dispatch() {
    switch (APIVersion) {
    case 1:
        use('file.1.ext');
        break;
    case 2:
        use('file.2.ext');
        break;
    case 3:
        use('file.3.ext');
        break;
    }
}
like image 43
Florian Margaine Avatar answered Oct 07 '22 10:10

Florian Margaine