Antes de comenzar a hablar sobre los principios de diseño de una API extensible, hay un mínimo higiénico a considerar. Una gran cantidad de problemas no habrían ocurrido si los desarrolladores de API fueran un poco más responsables en la identificación de su área de responsabilidad.
1. Proporcione la cantidad mínima de funcionalidad
En un momento dado, su API es como un iceberg: tiene una parte visible (documentada) y una parte invisible indocumentada. En una buena API, estas dos partes se relacionan entre sí aproximadamente como la superficie y la parte submarina de un iceberg real, 1 de cada 10. ¿Por qué? Por dos razones obvias.
Las computadoras existen para facilitar las cosas complejas, no al revés. El código que los desarrolladores escribirán en la parte superior de su API debe describir la solución a un problema complejo en términos simples y concisos. Si los desarrolladores se ven obligados a escribir más código en su API del que usted mismo escribió, algo salió mal aquí. Quizás tal API simplemente no sea necesaria.
Eliminar la funcionalidad de la API es imposible sin pérdidas graves. Si ha prometido proporcionar alguna funcionalidad, ahora debe proporcionarla "para siempre" (hasta que finalice el soporte para esta versión principal de la API). Declarar que la funcionalidad no es compatible es un proceso complejo, plagado de posibles conflictos con el consumidor.
La regla n. ° 1 es la más simple: si no tiene que exponer alguna funcionalidad, entonces no es necesario exponerla. Se puede formular de la siguiente manera: cada entidad, cada campo, cada método en la API pública es una solución de producto . Debe haber buenas razones por las que una entidad esté documentada.
2. Evite las áreas grises y la subestimación
, . , . , , , «» - , — 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.
Este es un borrador para un capítulo futuro del libro sobre desarrollo de API. El trabajo se realiza en Github . La versión en inglés del mismo capítulo se publica en medium . Le agradecería si pudiera compartirlo en reddit; yo mismo no puedo de acuerdo con la política de la plataforma.