How to support multiple mobile application versions with the most up-to-date server deployment? - rest

I'm trying to figure out a scenario, but I can't find any relevant information on the web.
Let's say I am deploying an Android Application (v1.0.0) with the backend (v1.0.0).
At some point, I will make some changes and update the app to v1.0.1 and the backend to v1.0.1 and they will work perfectly.
But how can I also support the previous version of the application (maybe the new server version provides another format of response for one specific request)?
I thought of having separate deployments for every version of the server, but for many updates, that would mean a big resources impact.
Also, forcing the users to update doesn't seem a good option in my opinion.

Essentially you can go multiple ways of doing it. Really depends on your requirements, but usually the reality is a mixture of the things below.
As a rule of thumb, think in data model that will be held compatible. If the contract can not be kept or your realize major changes are needed, introduce a new version of API. If old clients can not be supported, force update. You can also agree on a policy on how long to support each previous versions and then force update, this will make your life much easier and simpler, than maintaining tens of versions of APIs.
Backwards compatible data model
You must think backwards with each release:
Think of incremental modelling with each release cycle. So you can keep things.
When you forget about it and you need to switch behavior based on data:
Happened to me in my trainee years. Simply you have to decode which version it might be, based on the data if you forget to add protocol version. From the beginning you can always have a version field on the data. Moreover, you can also add a set of compatible parser versions.
Include protocol version in data:
{
"data": [ arbitrary data model],
"protocolVersion": "v1"
}
Based on the protocol version, you can decide how to process the data on the server side. You don't need to keep client version in mind, only the protocol's. Since it can be that you release: 1.0.0, 1.0.1, 1.1.0, and you only change protocol in 1.2.0.
But I think the problem is the that as data changes subsequently, so does behavior on server side processing.
Versioned API
Sometimes you see different paths for major versions:
/api/v1/query
/api/v2/query
Used when backwards compatibility is broken or after total reconsideration. Therefore not every version will have an increment.
Use a query parameter with the client version:
/api/query?v=1.0
/api/query?v=1.1
Similar to previous one, just written differently. Although I think this is not the way you want to go down.
Track client releases and used service versions
In reality there are multiple requests and multiple versions of services being used all times per one client version. This makes things even harder to maintain.
All the time, document and track. Version and release management is very important. Know the git hash from which version you built, many time it can get confusing and you just changed only one parameter after release as a quick fix and the day after nothing is compatible anymore.
Map all service versions to the client version at each release, know which commit you really built and use tagging and release management.
Test everything before each release
Have clear requirements for your backwards compatibility. Maybe you only support two older versions, then test with all the two clients, new client with the to be released server. Document everything. And when you meet your criteria for release, go with it.
Summary
Reality is a mixture of solutions. Have clear requirements on the backward compatibility. Therefore you can test before each release. When it is necessary, force update. Keep track of releases, and document each client versions with all the services being used with their versions.

Use switch case at the server for each different version of the app.

Related

Ensuring client updates to latest api version

I'm learning about the REST architecture style, and there are some things I don't understand when it comes to developing a back-end api for clients.
I've read about various approaches to versioning an http api, which all make sense, but how do you indicate to a client, when he's using an outdated version of your api, that he needs to update his version? Is there a way to do this without physically contacting the client and telling him that he needs to update his version?
I was thinking there might be some way to require the client to indicate his current version and give an appropriate message if it's outdated. Is this standard or even feasible?
Typically, clients update under one of two circumstances. Either they want functionality that's available in a more recent version, or you're dropping support for a prior version.
If you're planning on dropping support for an API version, you should definitely be notifying any customers you can find proactively. If they rely on your API version, and it disappears with no warning, they're going to be former customers.
In the vast majority of cases, clients of your API will not be scanning network traffic looking for a header or other indicator that the API is changing. Asking them to do so is non-standard and almost certainly not feasible.
Also, dropping support for an API version is a major shift. It causes upheaval in all of your clients, forcing them to make a code change in their applications by a date of your choice. It's not something to be done lightly.

How do you manage the underlying codebase for a versioned API?

I've been reading up on versioning strategies for ReST APIs, and something none of them appear to address is how you manage the underlying codebase.
Let's say we're making a bunch of breaking changes to an API - for example, changing our Customer resource so that it returns separate forename and surname fields instead of a single name field. (For this example, I'll use the URL versioning solution since it's easy to understand the concepts involved, but the question is equally applicable to content negotiation or custom HTTP headers)
We now have an endpoint at http://api.mycompany.com/v1/customers/{id}, and another incompatible endpoint at http://api.mycompany.com/v2/customers/{id}. We are still releasing bugfixes and security updates to the v1 API, but new feature development is now all focusing on v2. How do we write, test and deploy changes to our API server? I can see at least two solutions:
Use a source control branch/tag for the v1 codebase. v1 and v2 are developed, and deployed independently, with revision control merges used as necessary to apply the same bugfix to both versions - similar to how you'd manage codebases for native apps when developing a major new version whilst still supporting the previous version.
Make the codebase itself aware of the API versions, so you end up with a single codebase that includes both the v1 customer representation and the v2 customer representation. Treat versioning as part of your solution architecture instead of a deployment issue - probably using some combination of namespaces and routing to make sure requests are handled by the correct version.
The obvious advantage of the branch model is that it's trivial to delete old API versions - just stop deploying the appropriate branch/tag - but if you're running several versions, you could end up with a really convoluted branch structure and deployment pipeline. The "unified codebase" model avoids this problem, but (I think?) would make it much harder to remove deprecated resources and endpoints from the codebase when they're no longer required. I know this is probably subjective since there's unlikely to be a simple correct answer, but I'm curious to understand how organisations who maintain complex APIs across multiple versions are solving this problem.
I've used both of the strategies you mention. Of those two, I favor the second approach, being simpler, in use cases that support it. That is, if the versioning needs are simple, then go with a simpler software design:
A low number of changes, low complexity changes, or low frequency change schedule
Changes that are largely orthogonal to the rest of the codebase: the public API can exist peacefully with the rest of the stack without requiring "excessive" (for whatever definition of of that term you choose to adopt) branching in code
I did not find it overly difficult to remove deprecated versions using this model:
Good test coverage meant that ripping out a retired API and the associated backing code ensured no (well, minimal) regressions
Good naming strategy (API-versioned package names, or somewhat uglier, API versions in method names) made it easy to locate the relevant code
Cross-cutting concerns are harder; modifications to core backend systems to support multiple APIs have to be very carefully weighed. At some point, the cost of versioning backend (See comment on "excessive" above) outweighs the benefit of a single codebase.
The first approach is certainly simpler from the standpoint of reducing conflict between co-existing versions, but the overhead of maintaining separate systems tended to outweigh the benefit of reducing version conflict. That said, it was dead simple to stand up a new public API stack and start iterating on a separate API branch. Of course, generational loss set in almost immediately, and the branches turned into a mess of merges, merge conflict resolutions, and other such fun.
A third approach is at the architectural layer: adopt a variant of the Facade pattern, and abstract your APIs into public facing, versioned layers that talks to the appropriate Facade instance, which in turn talks to the backend via its own set of APIs. Your Facade (I used an Adapter in my previous project) becomes its own package, self-contained and testable, and allows you to migrate frontend APIs independently of the backend, and of each other.
This will work if your API versions tend to expose the same kinds of resources, but with different structural representations, as in your fullname/forename/surname example. It gets slightly harder if they start relying on different backend computations, as in, "My backend service has returned incorrectly calculated compound interest that has been exposed in public API v1. Our customers have already patched this incorrect behavior. Therefore, I cannot update that computation in the backend and have it apply until v2. Therefore we now need to fork our interest calculation code." Luckily, those tend to be infrequent: practically speaking, consumers of RESTful APIs favor accurate resource representations over bug-for-bug backwards compatibility, even amongst non-breaking changes on a theoretically idempotent GETted resource.
I'll be interested to hear your eventual decision.
For me the second approach is better. I have use it for the SOAP web services and plan to use it for REST also.
As you write, the codebase should be version aware, but a compatibility layer can be used as separate layer. In your example, the codebase can produce resource representation (JSON or XML) with first and last name, but the compatibility layer will change it to have only name instead.
The codebase should implement only the latest version, lets say v3. The compatibility layer should convert the requests and response between the newest version v3 and the supported versions e.g v1 and v2.
The compatibility layer can have a separate adapters for each supported version which can be connected as chain.
For example:
Client v1 request: v1 adapt to v2 ---> v2 adapt to v3 ----> codebase
Client v2 request: v1 adapt to v2 (skip) ---> v2 adapt to v3 ----> codebase
For the response the adapters function simply in the opposite direction. If you are using Java EE, you can you the servlet filter chain as adapter chain for example.
Removing one version is easy, delete the corresponding adapter and the test code.
Branching seems much better for me, and i used this approach in my case.
Yes as you already mentioned - backporting bug fixes will require some effort, but at the same time supporting multiple versions under one source base (with routing and all other stuff) will require you if not less, but at least same effort, making system more complicated and monstrous with different branches of logic inside (at some point of versioning you definetely will come to huge case() pointing to version modules having code duplicated, or having even worse if(version == 2) then...) .
Also dont forget that for regression purposes you still have to keep tests branched.
Regarding versioning policy: i would keep as max -2 versions from current, deprecating support for old ones - that would give some motivation for users to move.
Usually, introduction of a major version of API leading you in a situation of having to maintain multiple versions is an event which does not (or should not) occur very frequently. However, it cannot be avoided completely. I think it is overall a safe assumption that a major version, once introduced, would stay latest version for relatively long period of time. Based on this, I would prefer to achieve simplicity in the code at the expense of duplication as it gives me better confidence of not breaking previous version when I introduce changes in latest one.

What should be the next software version number?

My current live app is 1.2.3.
Internally i have released up to 1.2.3.5 for testing. I now need to do an emergency fix on the production app. this version should ideally be 1.2.4 , but it would be confusing, as it should have all changes upto 1.2.3.5 and it would not.
I cant make the new production app 1.2.3.1 because that was already released internally.
what should be the new version number for my app?
I would recommend something akin to 1.2.3 Update 1. Or, 1.2.3.0.1, although I personally think more than four version numbers is ugly and would go with the former. FWIW, Java also uses similar wording.
The other logical options collide with existing versions and have a good probability of causing confusion, as you have already pointed out.
Ideally I would begun using 1.2.4.x internally as soon as 1.2.3 was released, thereby reserving the rest of 1.2.3.x for out-of-band updates to the current production version. You may wish to adopt something like this for the future to avoid similar collisions, but it is truly personal preference.

Managing version files of Core data model

During development process we keep on changing core data model file.Supposing we have many model files each built on previous version. Then At the time of submitting the app to appstore can I delete all the versions except the latest one and the one on which it is based.
Basically how to manage all version files??
During pre-1.0 development it's much more typical to not bother with model versioning. Edit the model as needed, don't create new versions, and delete your existing data whenever it doesn't match the new model version. This would be a bad idea after release, but while in development it's usually fine.
If you do need to maintain different versions during development for some reason, there are really no special steps to take to get rid of the old ones. Make sure that the latest model version is the current version (which will almost certainly be true anyway) and then delete the old model files. Voila, you're done. You don't need the old model files unless people will be using the app who already have data that uses those models, and when you first release the app, that will not be the case.

What version number scheme for poorly planned, branched, and schizophrenic application

I'm looking for a version numbering scheme/pattern/system for an application that is currently branched into several versions with shell game style release dates. This has made versioning a nightmare. I'd like to just use the typical Major.Minor.Revision however this will break down for me quickly the way things are presently run around here.
Here is my inventory...
1.0.0 - Production version.
1.0.1 - Production revision version with bug fixes.
1.1.0 - Production minor version with new features due in July (regulations compliance, must be done).
1.2.0 - Production minor version with new features to integrate with not-yet-released-still-under-development System A.
2.0.0 - Development major version "2.0" of the product (code migrated to newer platform, usability improved).
And to make it more fun, they are planning another project (new features) for integration with a different system.
1.3.0 - Production minor version with new features integrating with System B.
Adding to the complexity is the fact that we don't know exactly when (read: the order in which) these will "go live". If one of the systems we are integrating with gets delayed, then management changes the release schedule. So version 1.2.0 today could get delayed and then the build we tagged as 1.3.0 would drop first. Coordinating with QA is difficult enough already without changing version labels at the end of the cycle.
Questions? Thoughts? Small furry animals?
peace|dewde
Sounds to me like you don't want to use version numbers specifically.
You can use codenames, (Windows did this with each of their releases before they were released).
You basically need something more than numbers to distinguish in house which branch you are talking about. As the versions are released you can slap a Major.Minor.Revision stamp on them, but until then you need to name them in a way that will be recognizable.
Split them into branches and sub-branches.
Make sure that anything dependant on a higher branch has a derivative name.
So, you could call a branch ProductionMac, and a branch ProductionWindows, and that way you would know instantly that they are not to be merged, and that they both derive from production.
The most important thing to maintain is the structural hierarchy. Version numbers do this fairly well, but you have to keep adding "." for each new layer, which is annoying and completely undescriptive (much like naming your variables variableOne,variableTwo,variableThree) So, make sure that however you choose to label each branch, it is still obvious which branches are related to which other branches.
Sounds like numbers aren't going to help much, I'd go with naming the releases after small furry animals.
Or, name each release after the project that spawned it ('UI overhaul', 'June maintenance' etc), and then only assign it a version number when it goes live?
I'd use a dictionary to map between internal development numbers and external "release" numbers, then use the internal development numbers internally and only expose the "release" numbers when you're ready to release it out of development.
Bonus points if you use an intermediate map using irrational numbers. "How is development on release 3.14159 going?" "Oh, not bad, but I'm still fixing a bug we found in release 2.71828183." "What? That bug? That was supposed to be fixed with minor release 1.73205!" :-)
As others have suggested, use a non-numeric codename internally, and apply a number as each component is released.
Appending a revision/build number to your versioning can help you match this internal codename to the external version number (and can aid in communication with QA).
For example:
RegulationCompliance r1234 corresponds to the release 1.1.0.1234.
Based on what you describe, I agree with the first couple of posts. Meaningful, unique names relevant to the scope/feature-set are probably the way to go for each branch. Numbered versions seem reasonable within each named branch.
What you really need... is Gmail-style labeling... for your versioning!
nth-ing the previous posts.
We have our build system increment the build # after each build (whether or not it is to be released) which is what dev/QA uses to identify builds. The final version # is ONLY exposed to the outside world when QA releases. So there are really multiple builds of 1.3.0.x, but only one true 1.3.0.
Here is another alternative I considered while churning on this yesterday. Perhaps I need to rethink what is considered major. Integrating with another system may be a small quantity of work, but if it impacts the scheduling and release dates and version in such a significant way, as it does for me here, maybe that alone is a large enough impact to bump the branch up to major status. Then some of my headache would be minimized.
The most likely scenarios for releasing versions out of order revolve around the minor iterations. The major ones take a coordinated, cross-departmental effort. You can see them on the horizon. The minor ones sneak up on you and fork everything up.
"Here are the new compliance
regulations. If they don't go live by
July 15th, we will be fined $500,000.
Per day."
"What? When did you get these?"
"Last July. Weren't you CC'd on the
distribution?"
** facepalm **
I still think Devinb's answer is best. But I wanted to throw this out here for others in this dilemma.
peace|dewde