Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

Mejores Prácticas para la Versionado de APIs RESTful: Por qué v1 es el número 1

Chris McFadden

24 may 2017

Correo electrónico

1 min read

Mejores Prácticas para la Versionado de APIs RESTful: Por qué v1 es el número 1

Chris McFadden

24 may 2017

Correo electrónico

1 min read

Mejores Prácticas para la Versionado de APIs RESTful: Por qué v1 es el número 1

¿Entonces, qué tan difícil puede ser versionar una API? La verdad es que no lo es, pero lo que es duro es mantener un poco de cordura al no caer innecesariamente en un número desconcertante de versiones y subversiones aplicadas a docenas de puntos finales de la API con compatibilidades poco claras.

Breaking Changes Malos! API Versioning Bueno!

Como cualquiera que haya construido o use regularmente una API se da cuenta tarde o temprano, los cambios disruptivos son muy malos y pueden ser una mancha muy seria en una API que de otro modo sería útil. Un cambio disruptivo es un cambio en el comportamiento de una API que puede romper la integración de un usuario y resultar en mucha frustración y pérdida de confianza entre el proveedor de la API y el usuario. Los cambios disruptivos requieren que los usuarios sean notificados con anticipación (con las correspondientes disculpas) en lugar de un cambio que simplemente se presenta, como una nueva característica encantadora. La forma de evitar esa frustración es versionar una API con garantías del propietario de la API de que no se introducirán cambios sorprendentes dentro de una sola versión.

Entonces, ¿qué tan difícil puede ser versionar una API? La verdad es que no lo es, pero lo difícil es mantener algo de cordura evitando desbordarse sin necesidad en un número vertiginoso de versiones y subversiones aplicadas a docenas de puntos finales de API con compatibilidades poco claras.

Introducimos la v1 de la API hace tres años y no nos dimos cuenta de que seguiría siendo fuerte hasta el día de hoy. Entonces, ¿cómo hemos continuado proporcionando la mejor API de entrega de correo electrónico durante más de dos años pero aún manteniendo la misma versión de API? Esta estabilidad es crucial para los desarrolladores que construyen aplicaciones con APIs de correo electrónico en infraestructuras de nube, donde la fiabilidad y la consistencia son primordiales. Aunque hay muchas opiniones diferentes sobre cómo versionar APIs REST, espero que la historia de nuestra humilde pero poderosa v1 pueda guiarte en tu camino hacia la iluminación en versionado de APIs.

REST Es Mejor

El SparkPost API se origina de cuando éramos Message Systems, antes de nuestras aventuras en la nube. En ese momento estábamos ocupados haciendo los preparativos finales para el lanzamiento beta de Momentum 4. Esta fue una importante actualización de la versión 3.x, nuestro MTA líder en el mercado local. Momentum 4 incluyó una interfaz de usuario completamente nueva, análisis en tiempo real y, lo más importante, una nueva API web para la inyección y generación de mensajes, gestión de plantillas y obtención de métricas de correo electrónico. Nuestra visión era de una arquitectura de API primero, donde incluso la interfaz de usuario interactuaría con los puntos finales de la API.

Una de las primeras y mejores decisiones que tomamos fue adoptar un estilo RESTful. Desde finales de la década de 2000, la transferencia de estado representacional (REST) es el estándar de facto de las APIs en la nube. Usar HTTP y JSON facilita a los desarrolladores, independientemente del lenguaje de programación que usen – PHP, Ruby y Java – integrarse con nuestra API sin conocer o preocuparse por nuestra tecnología subyacente. Sin embargo, construir APIs nativas de la nube a escala puede presentar desafíos inesperados de infraestructura, como los límites de escalado de DNS que encontramos en AWS al manejar tráfico de API de alto volumen.

Elegir usar la arquitectura RESTful fue fácil. Elegir una convención de versionado no fue tan sencillo. Inicialmente pospusimos la cuestión del versionado al no versionar el beta en absoluto. Sin embargo, en un par de meses, el beta estaba en manos de unos pocos clientes y comenzamos a desarrollar nuestro servicio en la nube. Era hora de versionar. Evaluamos dos convenciones de versionado. La primera era poner el versionado directamente en el URI y la segunda era usar un encabezado Accept. La primera opción es más explícita y menos complicada, lo que es más fácil para los desarrolladores. Dado que amamos a los desarrolladores, fue la elección lógica.

El SparkPost API se origina de cuando éramos Message Systems, antes de nuestras aventuras en la nube. En ese momento estábamos ocupados haciendo los preparativos finales para el lanzamiento beta de Momentum 4. Esta fue una importante actualización de la versión 3.x, nuestro MTA líder en el mercado local. Momentum 4 incluyó una interfaz de usuario completamente nueva, análisis en tiempo real y, lo más importante, una nueva API web para la inyección y generación de mensajes, gestión de plantillas y obtención de métricas de correo electrónico. Nuestra visión era de una arquitectura de API primero, donde incluso la interfaz de usuario interactuaría con los puntos finales de la API.

Una de las primeras y mejores decisiones que tomamos fue adoptar un estilo RESTful. Desde finales de la década de 2000, la transferencia de estado representacional (REST) es el estándar de facto de las APIs en la nube. Usar HTTP y JSON facilita a los desarrolladores, independientemente del lenguaje de programación que usen – PHP, Ruby y Java – integrarse con nuestra API sin conocer o preocuparse por nuestra tecnología subyacente. Sin embargo, construir APIs nativas de la nube a escala puede presentar desafíos inesperados de infraestructura, como los límites de escalado de DNS que encontramos en AWS al manejar tráfico de API de alto volumen.

Elegir usar la arquitectura RESTful fue fácil. Elegir una convención de versionado no fue tan sencillo. Inicialmente pospusimos la cuestión del versionado al no versionar el beta en absoluto. Sin embargo, en un par de meses, el beta estaba en manos de unos pocos clientes y comenzamos a desarrollar nuestro servicio en la nube. Era hora de versionar. Evaluamos dos convenciones de versionado. La primera era poner el versionado directamente en el URI y la segunda era usar un encabezado Accept. La primera opción es más explícita y menos complicada, lo que es más fácil para los desarrolladores. Dado que amamos a los desarrolladores, fue la elección lógica.

El SparkPost API se origina de cuando éramos Message Systems, antes de nuestras aventuras en la nube. En ese momento estábamos ocupados haciendo los preparativos finales para el lanzamiento beta de Momentum 4. Esta fue una importante actualización de la versión 3.x, nuestro MTA líder en el mercado local. Momentum 4 incluyó una interfaz de usuario completamente nueva, análisis en tiempo real y, lo más importante, una nueva API web para la inyección y generación de mensajes, gestión de plantillas y obtención de métricas de correo electrónico. Nuestra visión era de una arquitectura de API primero, donde incluso la interfaz de usuario interactuaría con los puntos finales de la API.

Una de las primeras y mejores decisiones que tomamos fue adoptar un estilo RESTful. Desde finales de la década de 2000, la transferencia de estado representacional (REST) es el estándar de facto de las APIs en la nube. Usar HTTP y JSON facilita a los desarrolladores, independientemente del lenguaje de programación que usen – PHP, Ruby y Java – integrarse con nuestra API sin conocer o preocuparse por nuestra tecnología subyacente. Sin embargo, construir APIs nativas de la nube a escala puede presentar desafíos inesperados de infraestructura, como los límites de escalado de DNS que encontramos en AWS al manejar tráfico de API de alto volumen.

Elegir usar la arquitectura RESTful fue fácil. Elegir una convención de versionado no fue tan sencillo. Inicialmente pospusimos la cuestión del versionado al no versionar el beta en absoluto. Sin embargo, en un par de meses, el beta estaba en manos de unos pocos clientes y comenzamos a desarrollar nuestro servicio en la nube. Era hora de versionar. Evaluamos dos convenciones de versionado. La primera era poner el versionado directamente en el URI y la segunda era usar un encabezado Accept. La primera opción es más explícita y menos complicada, lo que es más fácil para los desarrolladores. Dado que amamos a los desarrolladores, fue la elección lógica.

Gobernanza API

Con una convención de versionado seleccionada, teníamos más preguntas. ¿Cuándo subiríamos la versión? ¿Qué es un cambio de ruptura? ¿Reversionaríamos toda la API o solo ciertos puntos finales? En SparkPost, tenemos múltiples equipos trabajando en diferentes partes de nuestra API. Dentro de esos equipos, las personas trabajan en diferentes puntos finales en diferentes momentos. Por lo tanto, es muy importante que nuestra API sea consistente en el uso de convenciones. Esto era más grande que el versionado.

Establecimos un grupo de gobernanza que incluye ingenieros que representan a cada equipo, un miembro del equipo de Product Management y nuestro CTO. Este grupo es responsable de establecer, documentar y hacer cumplir nuestras convenciones de API en todos los equipos. Un canal de Slack de gobernanza de API también es útil para debates animados sobre el tema.

El grupo de gobernanza identificó una serie de formas en que los cambios pueden introducirse en la API que son beneficiosos para el usuario y no constituyen un cambio de ruptura. Estos incluyen:

  • Un nuevo recurso o punto final de API

  • Un nuevo parámetro opcional

  • Un cambio a un punto final de API no público

  • Una nueva clave opcional en el cuerpo de la solicitud JSON POST

  • Una nueva clave devuelta en el cuerpo de la respuesta JSON


Por el contrario, un cambio de ruptura incluyó cualquier cosa que podría romper la integración de un usuario, tal como:

  • Un nuevo parámetro requerido

  • Una nueva clave requerida en cuerpos POST

  • Eliminación de un punto final existente

  • Eliminación de un método de solicitud de punto final existente

  • Un comportamiento interno materialmente diferente de una llamada API, como un cambio en el comportamiento predeterminado.

The Big 1.0

A medida que documentamos y discutimos estas convenciones, también llegamos a la conclusión de que era en el mejor interés de todos (¡incluido el nuestro!) evitar hacer cambios disruptivos en el API ya que manejar múltiples versiones añade bastante complejidad. Decidimos que había algunas cosas que deberíamos arreglar con nuestro API antes de comprometernos a "v1".

Enviar un correo electrónico simple requería demasiado esfuerzo. Para "mantener las cosas simples" actualizamos el cuerpo POST para asegurar que se acomoden tanto casos de uso simples como complejos. El nuevo formato también era más preparado para el futuro. En segundo lugar, abordamos un problema con el endpoint de Métricas. Este endpoint utilizaba un parámetro "group_by" que cambiaría el formato del cuerpo de la respuesta GET de tal manera que la primera clave sería el valor del parámetro de agrupación. Eso no parecía muy RESTful, por lo que dividimos cada agrupación en un endpoint separado. Finalmente, auditamos cada endpoint e hicimos cambios menores aquí y allá para asegurar que se ajustaran a los estándares.

Documentación Precisa

Es importante tener una documentación de API precisa y utilizable para evitar cambios disruptivos, ya sean deliberados o no. Decidimos usar un enfoque simple de documentación de API aprovechando un lenguaje Markdown llamado API Blueprint y gestionar nuestros documentos en Github. Nuestra comunidad contribuye y mejora estos documentos de código abierto. También mantenemos un conjunto de documentos no públicos en Github para APIs y endpoints internos.

Inicialmente, publicamos nuestros documentos en Apiary, una gran herramienta para hacer prototipos y publicar documentos de API. Sin embargo, integrar Apiary en nuestro sitio web no funciona en dispositivos móviles, por lo que ahora usamos Jekyll para generar documentos estáticos. Nuestros más recientes SparkPost API docs ahora se cargan rápidamente y funcionan bien en dispositivos móviles, lo cual es importante para los desarrolladores que no siempre están sentados frente a su computadora.

Separando Deployment de Release

Aprendimos desde el principio el truco valioso de separar una implementación de un lanzamiento. De esta manera es posible implementar cambios con frecuencia cuando están listos a través de la entrega y despliegue continuos, pero no siempre los anunciamos o documentamos públicamente al mismo tiempo. No es raro para nosotros implementar un nuevo punto de acceso API o una mejora a un punto de acceso API existente y usarlo desde la interfaz de usuario o con herramientas internas antes de documentarlo y soportarlo públicamente. De esa manera, podemos hacer algunos ajustes para la usabilidad o conformidad con los estándares sin preocuparnos por realizar un temido cambio incompatible. Una vez que estamos satisfechos con el cambio, lo añadimos a nuestra documentación pública.

¡Doh!

Es justo admitir que ha habido ocasiones en las que no hemos cumplido nuestros ideales de «sin cambios disruptivos» y de estas vale la pena aprender. En una ocasión, decidimos que sería mejor para los usuarios si una cierta propiedad predeterminada fuese true en lugar de false. Después de implementar el cambio, recibimos varias quejas de los usuarios ya que el comportamiento había cambiado inesperadamente.  Revertimos el cambio y añadimos una configuración a nivel de cuenta – un enfoque mucho más amigable para el usuario, sin duda.

Ocasionalmente, estamos tentados a introducir cambios disruptivos como resultado de correcciones de errores. Sin embargo, decidimos dejar estas idiosincrasias solas en lugar de arriesgarse a romper las integraciones de los clientes por el bien de la consistencia.

Existen casos raros en los que tomamos la seria decisión de realizar un cambio disruptivo – como dejar obsoleto un recurso o método API – en beneficio de la mayor comunidad de usuarios y solo después de confirmar que hay poco o ningún impacto para los usuarios. Por ejemplo, tomamos deliberadamente la decisión de alterar el comportamiento de respuesta del Suppression API pero solo después de ponderar cuidadosamente los beneficios y los impactos para la comunidad y comunicar cuidadosamente el cambio a nuestros usuarios. Sin embargo,  nunca  introduciríamos un cambio que tenga una remota posibilidad de impactar directamente en el envío de un correo electrónico de producción del usuario.

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Company

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Company

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

R

Reach

G

Grow

M

Manage

A

Automate

Company

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.