- Las decisiones sobre el nombrado y modelado de recursos de API son la parte más difícil e importante del diseño de API. Los recursos forman el modelo mental del usuario sobre cómo funciona el producto y sus capacidades.
- El equipo de Increase usa el principio de "sin abstracciones" para orientar el diseño de su API.
El enfoque de Stripe para el diseño de API
- Una parte considerable del equipo de Increase trabajó antes en Stripe y toma en cuenta los valores detrás del exitoso diseño de API de Stripe.
- Stripe sobresale en extraer la funcionalidad central de dominios complejos en abstracciones que los usuarios pueden entender y usar con facilidad. (Ejemplo:
PaymentIntent, que abstrae las diferencias entre Visa y Mastercard)
- La mayoría de los usuarios de Stripe son startups en etapas tempranas que desarrollan productos no relacionados con pagos, por lo que no necesitan conocer los detalles de las tarjetas de crédito. Quieren integrar Stripe rápidamente y enfocarse en construir su producto.
Los usuarios de Increase y sus principios de diseño de API
- En cambio, los usuarios de Increase tienen un conocimiento profundo de las redes de pago, y eligieron Increase precisamente por su conexión directa a la red y la profundidad de integración.
- Quieren saber con exactitud cuándo cierra la ventana de FedACH y en qué momento se realiza una transferencia, y entienden que configurar distintos códigos SEC en una transferencia ACH puede afectar el momento de una devolución.
- Intentar ocultar la complejidad fundamental de estas redes no simplifica la vida de los usuarios; solo los frustra.
- A partir de conversaciones con usuarios iniciales, derivaron el principio de "sin abstracciones" y lo aplicaron al diseño de la API.
Cómo afectó el principio de "sin abstracciones" al diseño de la API
- Usar la terminología real: en lugar de inventar nombres propios para los recursos y atributos de la API, usan el vocabulario de la red subyacente. (Ejemplo: los parámetros de transferencias ACH usan nombres de campo de la especificación Nacha)
- Inmutabilidad: al usar eventos reales como modelo, más recursos de API pueden ser inmutables. Resulta efectivo agrupar clústeres de recursos inmutables en "objetos de ciclo de vida" de máquina de estados. (Ejemplo: el campo
status del objeto ach_transfer y varios subobjetos inmutables creados según el ciclo de vida de la transferencia)
- Separar recursos por caso de uso: cuando el conjunto de acciones que el usuario puede tomar cambia mucho según la instancia del recurso, lo dividen en varios recursos. (Ejemplo: las transferencias ACH salientes y entrantes se separan en recursos distintos)
Cumplimiento del enfoque por parte del equipo de ingeniería
- El equipo de ingeniería se comprometió a seguir este enfoque.
- Al diseñar una API compleja durante años, siempre hay que tomar pequeñas decisiones incrementales; comprometerse de antemano a seguir principios base reduce la carga cognitiva de esas decisiones.
- Por ejemplo, en el caso del campo Input Message Accountability Data requerido al enviar dinero a la Reserva Federal, en una API con mucha abstracción habría que pensar cómo renombrarlo de forma "amigable para el usuario", pero en Increase los ingenieros simplemente nombran el campo
input_message_accountability_data y siguen adelante.
Opinión de GN⁺
- El nivel de abstracción de una API puede variar según la experiencia del desarrollador con el dominio del producto y la energía que esté dispuesto a invertir en la integración. Por eso, al diseñar una API, es importante considerar el nivel de abstracción adecuado para quienes la van a integrar.
- Si se construye una API con un alto nivel de abstracción, hay que pensar cuidadosamente antes de agregar nuevas funciones. En cambio, si se construye una API con un bajo nivel de abstracción, hay que mantener esa línea y resistir la tentación de agregar abstracciones.
- Usar tal cual la terminología de la red o protocolo subyacente puede ayudar a los desarrolladores a entender el sistema subyacente, pero también puede convertirse en una barrera de entrada para quienes se enfrentan a él por primera vez. Por eso, parece importante contar con buenas anotaciones y documentación.
- Usar objetos inmutables al diseñar una API puede ser efectivo para mantener la consistencia de los datos y evitar side effects. Pero, por otro lado, puede resultar incómodo cuando se necesita actualizar datos, así que hay que considerar bien ese trade-off.
- Separar recursos por caso de uso puede aumentar la complejidad de la API, pero a largo plazo puede mejorar la predictibilidad. Aun así, si se fragmenta demasiado, la usabilidad puede verse afectada, por lo que es importante encontrar el nivel adecuado.
1 comentarios
Comentarios de Hacker News
Es bueno ofrecer tanto una API con abstracciones de bajo nivel como una API con abstracciones de alto nivel
Me gustó la parte que explica por qué Increase eligió un enfoque distinto
La verdadera capacidad de Stripe es conocer a sus clientes y ofrecer la simplicidad que quieren
Es similar al patrón de diseño "Ubiquitous Language" del Domain-Driven Design, donde se usan en la implementación los mismos términos reales que utilizan los expertos del dominio
Se debe usar un lenguaje que los expertos del dominio puedan entender
Sin abstracciones como POSIX, las aplicaciones tendrían que escribir adaptadores para cada sistema de archivos compatible
Se menciona que parte de la estructura de la API se construye en una relación 1:1 con base en especificaciones controladas externamente
Algo difícil de modelar limpiamente en una API de pagos es que los esquemas de pago representan de forma distinta los roles del pagador y del beneficiario cuando ocurre una devolución de pago