Bevor wir über die Designprinzipien einer erweiterbaren API sprechen, sollten wir das Hygieneminimum diskutieren. Eine große Anzahl von Problemen wäre nicht aufgetreten, wenn die API-Entwickler bei der Identifizierung ihres Verantwortungsbereichs etwas verantwortungsbewusster gewesen wären.
1. Stellen Sie die Mindestfunktionalität bereit
Zu jedem Zeitpunkt ist Ihre API wie ein Eisberg: Sie hat einen sichtbaren (dokumentierten) Teil und einen unsichtbaren undokumentierten Teil. In einer guten API beziehen sich diese beiden Teile ungefähr wie die Oberfläche und der Unterwasserteil eines echten Eisbergs aufeinander, 1 zu 10. Warum ist das so? Aus zwei offensichtlichen Gründen.
Computer existieren, um komplexe Dinge einfach zu machen, nicht umgekehrt. Der Code, den Entwickler über Ihre API schreiben, sollte die Lösung eines komplexen Problems in einfachen und präzisen Worten beschreiben. Wenn Entwickler mehr Code in Ihre API schreiben müssen, als Sie selbst geschrieben haben, ist hier ein Fehler aufgetreten. Vielleicht wird eine solche API einfach nicht benötigt.
Das Entfernen von Funktionen aus der API ist ohne ernsthafte Verluste nicht möglich. Wenn Sie versprochen haben, einige Funktionen bereitzustellen, müssen Sie diese jetzt "für immer" bereitstellen (bis zum Ende der Unterstützung für diese Hauptversion der API). Das Deklarieren der nicht unterstützten Funktionalität ist ein komplexer Prozess, der mit potenziellen Konflikten mit dem Verbraucher behaftet ist.
Regel 1 ist die einfachste: Wenn Sie einige Funktionen nicht verfügbar machen müssen, müssen Sie sie nicht verfügbar machen. Es kann wie folgt formuliert werden: Jede Entität, jedes Feld, jede Methode in der öffentlichen API ist eine Produktlösung . Es muss einen guten Grund geben, warum eine Entität dokumentiert wird.
2. Vermeiden Sie Grauzonen und Understatement
, . , . , , , «» - , — API, , . «» . .
API , :
;
— , , ..;
. , , .
3.
. , : - , , ?
1. SDK .
//
let order = api.createOrder();
//
let status = api.getStatus(order.id);
, - . , id 404
, , . , strong eventual.
? , . , — . , — .
: «, !» — , , . , , createOrder
, SDK - :
let order = api.createOrder();
let status;
while (true) {
try {
status = api.getStatus(order.id);
} catch (e) {
if (e.httpStatusCode != 404 || timeoutExceeded()) {
break;
}
}
}
if (status) {
…
}
, , , . API, createOrder
SDK , getStatus
.
— API. , , .
2. :
let resolve;
let promise = new Promise(
function (innerResolve) {
resolve = innerResolve;
}
);
resolve();
, callback-, new Promise
, resolve
resolve()
. : new Promise
callback-.
, , . API — . , ; , , API. .
3. , API , :
//
//
//
object.animateWidth('100px', '500px', '1s');
//
object.observe('widthchange', observerFunction);
: observerFunction
? , SDK 10 — observerFunction 10 '140px', '180px' .. '500px'. API — , observerFunction
.
- — , , , , SDK 10 . , , observerFunction
'500px' - — - .
— callback — .
4. , , :
GET /v1/orders/{id}/events/history
→
{
"event_history": [
{
"iso_datetime": "2020-12-29T00:35:00+03:00",
"new_status": "created"
},
{
"iso_datetime": "2020-12-29T00:35:10+03:00",
"new_status": "payment_approved"
},
{
"iso_datetime": "2020-12-29T00:35:20+03:00",
"new_status": "preparing_started"
},
{
"iso_datetime": "2020-12-29T00:35:30+03:00",
"new_status": "ready"
}
]
}
, - « », . .. "preparing_started", "ready", "payment_approved". , - — , . , , .
, (, - ) - , - — , . , - , . . - ; , .
-, ; -, "payment_approved" "preparing_started" ( — , , ) .
.
4.
, , — . - , .
, , - . - , «». , , . - , .. -, , , - , .
« -» — , , - , . . «» — API; — « », III.
Dies ist ein Entwurf für ein zukünftiges Kapitel des Buches zur API-Entwicklung. Die Arbeit wird an Github erledigt . Die englische Version desselben Kapitels wird auf Medium veröffentlicht . Ich würde es begrüßen, wenn Sie es auf reddit teilen können - ich selbst kann es nicht gemäß den Plattformrichtlinien.