The document discusses strategies for maintaining backwards compatibility when making changes to APIs and data models. It introduces the Tolerant Reader and Magnanimous Writer patterns which aim to handle changes in a backwards compatible way. The Tolerant Reader pattern makes clients robust to unknown or extra fields, while the Magnanimous Writer pattern ensures servers are flexible in what they accept and return. These patterns, along with techniques like default values and migration rules, can help navigate the "versioning hell" that occurs if changes break existing clients and interfaces.
34. Tolerant Reader Pattern
Tolerant gegenüber unbekannten Feldern
Umgang mit x-extensible-enum
http://zalando.github.io/restful-api-guidelines
Tolerant gegenüber unbekannten Statuscodes
HTTP Status 301 folgen
40. Und was ist, wenn der Client kein
Tolerant Reader ist?
41. PROJEKTIONEN
// Client kann entscheiden, welche Felder er bekommen möchte
// Facebook Style
GET /addresses/3?fields=street,city
GET /addresses/3?fields=street.name,street.number,city
// LinkedIn Style
GET /addresses/3?fields=street:(name,number),city
42. OK, so soll sich
der Client verhalten.
Aber was ist mit dem Server?
43. Photo by Irene Fertik, USC News Service. Copyright 1994, USC.
„Be conservative in what you do,
Be liberal in what you accept
from others“
RFC 793, Robustness Principal (John Postel)
44. Es darf nichts entfernt werden
Keine Veränderung von Verarbeitungsregel
Optionales darf nie Required werden
http://zalando.github.io/restful-api-guidelines
Alles was hinzugefügt wird, muss optional sein
57. MERGE PATCH UND NULL VALUES
public class Street {
private String streetName;
private String streetNumber;
public void setName(String name) { setStreetName(...
public void setNumber(String number) { setStreetNum...
}
Wird mit null aufgerufen
Wird gar nicht aufgerufen
58. MERGE PATCH UND NULL VALUES
public class Street {
private String streetName; // = null
private String streetNumber; // = null
public void setName(String name) { setStreetName(...
public void setNumber(String number) { setStreetNum...
}
59. MERGE PATCH UND NULL VALUES
public class Street {
private String streetName; // = null
private String streetNumber; // = null
public void setName(String name) { setStreetName(...
public void setNumber(String number) { setStreetNum...
}
Simple Solution:
Don‘t use PATCH at all
60. MERGE PATCH UND NULL VALUES
public class Street {
private String streetName; // = null
private String streetNumber; // = null
public void setName(String name) { setStreetName(...
public void setNumber(String number) { setStreetNum...
}
Advanced Solution:
Use initial values
61. MERGE PATCH UND NULL VALUES
public class Street {
private String streetName = "<initial value>";
private String streetNumber = "<initial value>";
public void setName(String name) { setStreetName(...
public void setNumber(String number) { setStreetNum...
}
62. MERGE PATCH UND NULL VALUES
public class Street {
private String streetName = "<initial value>";
private String streetNumber = "<initial value>";
public void setName(String name) { setStreetName(...
public void setNumber(String number) { setStreetNum...
}
Wird mit null aufgerufen
Wird gar nicht aufgerufen
63. MERGE PATCH UND NULL VALUES
public class Street {
private String streetName; // = null
private String streetNumber = "<initial value>";
public void setName(String name) { setStreetName(...
public void setNumber(String number) { setStreetNum...
}
Wird mit null aufgerufen
Wird gar nicht aufgerufen
83. PIPELINE TO DEPLOY TO STAGE
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
84. PIPELINE TO DEPLOY TO STAGE
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
Achtung:
Abwärtskompatibilität ist
trotzdem notwendig!
85. BREAKING CHANGE VOM PROVIDER
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
86. BREAKING CHANGE VOM CONSUMER
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
91. Version 2.0
ist nur inkompatibel zu 1.0!
Version 2.0 ist identisch zu 1.x!
Das erleichtert das Mapping
zwischen den Versionen!
92. Ein solcher Versionssprung ist
nicht anforderungsgetrieben,
sondern viel besser und
langfristiger planbar
93. Wenn eine neue Version
nicht auf die alte abbildbar ist,
ist es keine neue Version,
sondern eine neue Schnittstelle!
94. • Über URL-Pfad
/v2/addresses
• Über Query-Parameter
/addresses?version=v2
• Über Version-Header
X-Api-Version: v2
• Über Version-Attribut am Media-Type
application/xml;version=v2
• Über Media-Type
application/vnd.de.openknowledge+v2+json
ERMITTELN DER VERSION