the science and art of backwards compatibility
TRANSCRIPT
![Page 1: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/1.jpg)
Backwards CompatibilityThe Science and the Art
![Page 2: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/2.jpg)
Agenda
Where does backwards compatibility matter, and why?
Ways a ReST service can evolve. Strategies for evolving a service in a backwards
compatible fashion. Database backwards compatibility. Best practices.
![Page 3: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/3.jpg)
So you want to deploy a new version
The new version has a different API than the old one. Typically, web service Also: java library Also: schema design
![Page 4: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/4.jpg)
Just upgrade the clients?
May not be able to upgrade all clients at the same time.
Creates tightly coupled releases. Cannot do partial rollbacks.
Not possible for zero-downtime deploys.
![Page 5: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/5.jpg)
Versioning?
/myService/v1 → /myService/v2
![Page 6: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/6.jpg)
Backwards Compatibility
A change to a service is backwards compatible if old clients can continue to call the new service without problems.
![Page 7: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/7.jpg)
Wire Compatibility
Data format not changed in ways that cause parsing errors when old clients make calls.
![Page 8: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/8.jpg)
Semantic Compatibility
When old clients make calls, stuff still works right.
This is the one you want!
![Page 9: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/9.jpg)
Compatibility and deploys
A backwards compatible service change can be rolled out without problems. Zero downtime!
Rolling back other services does not force rolling back your service.
![Page 10: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/10.jpg)
Compatibility and deploys
After (and only after) a service has rolled, can clients upgrade. Or perhaps just change a config flag
If the service needs to roll back, all clients must roll back first.
![Page 11: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/11.jpg)
Ways a ReST service can evolve
Changes to the API For web services, this includes URIs, representations (i.e.
JSON), and HTTP methods Changes to behavior Most evolutions involve both kinds of change
![Page 12: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/12.jpg)
Evolution Strategies
Additional field in request Additional field in response New values in existing request fields Changing field types
![Page 13: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/13.jpg)
Additional field in request
Make it optional (at least at first), with a default value matching old behavior @RequestMapping(value=”/petstore/pets”, method=GET) public getPets() { return petService.getAllPets(); }
@RequestMapping(value=”/petstore/pets”, method=GET) public getPets( @RequestParam(value=“species”, required=false)
Species species) { return species == null ? petService.getAllPets() : petService.getAllPets(species); }
![Page 14: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/14.jpg)
Additional field in request
Can also provide a default value: @RequestMapping(value=”/petstore/pets”, method=GET) public getPets(
@RequestParam(“species”) species)
@RequestMapping(value=”/petstore/pets”, method=GET) public getPets(
@RequestParam(“species”) Species species, @RequestParam( value=”mustBeAdoptable”, defaultValue=”false”)
boolean adoptable)
![Page 15: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/15.jpg)
Additional field in response
Most serialization libraries (including Jackson) can ignore unmapped fields.
New clients can use the field value, while old ones ignore it.
Ensure that the new field does not change semantics of old fields!
![Page 16: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/16.jpg)
New values in a request field
Pretty straightforward, provided that the meaning of pre-existing values does not change.
Example – add a new value to an enum.
public enum Species { DOG, FERRET, CAT }
![Page 17: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/17.jpg)
Narrowing set of allowed request values
Example – No longer allowing searches for Ferrets.
Rarely happens When it does, all clients must upgrade first
before the service can safely rely on the narrowed set of values
![Page 18: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/18.jpg)
Changing type
Of request field: Make sure the old type can be parsed into the new type –
e.g. Integer to Double Of response field:
Make sure new type can be parsed as old value – e.g. Double to Integer
Alternative: add new field with new type, have the old field “forward”
![Page 19: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/19.jpg)
Changing type – forwarding field
{“age”: 12} { “age”: 12, “ageAsDouble”: 12.3 }
![Page 20: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/20.jpg)
New behavior
Changing business logic Should be OK - this is why we do services in the first place!
Performing additional actions (or less actions) If this breaks contract, then a new resource may be
required New failure modes
This is very similar to new values in response fields
![Page 21: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/21.jpg)
Database backwards compatibility
Adding columns, tables, etc is OK...ish They won't always get used! Backwards population may be needed Beware the generic update endpoint!
Removing: First update clients If you know what they are!
Triggers and views can help here.
![Page 22: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/22.jpg)
Safely adding a column (say, “foo”)
Problem: old client calls GET, followed by PUT. Drops foo on the floor
Solution: BEFORE UPDATE trigger IF :new.foo IS NULL THEN :new.foo = :old.foo For inserts, a default value is simpler than a trigger.
![Page 23: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/23.jpg)
Best Practices
Plan ahead for versioning changes Keep your API as narrow as possible. Document and test compatibility requirements. Automated client tests. Keep clients as up to date as possible.
![Page 24: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/24.jpg)
Plan ahead for versioning changes
Always consider versioning issues when making any changes to existing resources. Do this up front, not as an afterthought.
Put care into initial API design. Keep DTOs as simple as possible.
It is very hard to see which fields clients are using.
![Page 25: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/25.jpg)
Keep your API as narrow as possible
You can't break what you never provided. Splunk can show what is called, but not how
the results are used. Narrow APIs often are also better tailored. Avoid generic “update” endpoints if possible Fields are part of the API – only include what
you need!
![Page 26: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/26.jpg)
Document and test compatibility requirements
Make it clear which client versions are expected to be able to talk to which service versions.
Verifying these requirements should be part of any service change.
![Page 27: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/27.jpg)
Automated tests
Write automated tests which exercise the service as a given version of a client would.
Tests for version n should be written before starting version n+1, and ideally before rolling version n to production.
Run old tests against new service version to test backwards compatibility.
Copy and paste can be acceptable here.
![Page 28: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/28.jpg)
Keep clients as up to date as possible
Once all clients have upgraded, any deprecated fields, resources, etc. can be removed from the service.
Maintaining backwards compatibility is expensive, and gets more so with multiple versions.
Cooperation is required.
![Page 29: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/29.jpg)
What if you need to break backwards compatability?
1)Don't!2)See #13)Talk with your colleagues – find a solution.4)There is always a way, and it usually isn't that
hard.
![Page 30: THE SCIENCE AND ART OF BACKWARDS COMPATIBILITY](https://reader036.vdocuments.net/reader036/viewer/2022070522/58ef10161a28ab480a8b45bb/html5/thumbnails/30.jpg)
THANK YOU.