Prácticas recomendadas para el control de versiones de API RESTful: Por qué v1 es #1

Prácticas recomendadas para el control de versiones de API RESTful: Por qué v1 es #1

Prácticas recomendadas para el control de versiones de API RESTful: Por qué v1 es #1

May 24, 2017

Publicado por

Publicado por

Chris McFadden

Chris McFadden

-

Categoría:

Categoría:

Email

Email

Ready to see Bird
in action?

Ready to see Bird
in action?

RESTful API Versioning Best Practices: Why v1 is #1

Breaking Changes Bad!  API Versioning Good!

Como cualquiera que haya construido o utilice regularmente una API se da cuenta tarde o temprano, los cambios de última hora son muy malos y pueden ser una mancha muy grave en una API por lo demás útil. Un cambio de última hora es un cambio en el comportamiento de una API que puede romper la integración de un usuario y provocar mucha frustración y pérdida de confianza entre el proveedor de la API y el usuario. Los cambios de última hora requieren que se notifique a los usuarios con antelación (con los correspondientes mea culpas) en lugar de un cambio que simplemente aparece, como una nueva característica encantadora. La forma de evitar esa frustración es versionar una API con garantías por parte del propietario de la API de que no se introducirán cambios sorprendentes dentro de una misma versión.


¿Es difícil versionar una API? La verdad es que no, pero lo que sí es difícil es mantener la cordura y no caer innecesariamente en un número vertiginoso de versiones y subversiones aplicadas a docenas de puntos finales de API con compatibilidades poco claras.


We introduced v1 of the API three years ago and did not realize that it would be going strong to this day. So how have we continued to provide the best email delivery API for over two years but still maintain the same API version? While there are many opiniones diferentes on how to version REST APIs, I hope that the story of our humble yet powerful v1 might guide you on your way to API versioning enlightenment.


REST es lo mejor

La API SparkPost tiene su origen en la época en que éramos Message Systems, antes de nuestras aventuras en la nube. Por aquel entonces estábamos ocupados con los últimos preparativos para el lanzamiento de la versión beta de Momentum 4. Se trataba de una importante actualización de la versión 3.x, nuestro MTA local líder del mercado. Momentum La 4 incluía una interfaz de usuario completamente nueva, análisis en tiempo real y, lo que es más importante, una nueva API web para la inyección y generación de mensajes, la gestión de plantillas y la obtención de métricas de correo electrónico. Nuestra visión era la de una arquitectura API first, en la que incluso la interfaz de usuario interactuara con los puntos finales de la API.


One of the earliest and best decisions we made was to adopt a RESTful style. Since the late 2000s representational state transfer (REST) based web APIs are the de-facto standard of cloud APIs. Using HTTP and JSON makes it easy for developers, regardless of which programming language they use – PHP, Ruby, and Java – to integrate with our API without knowing or caring about our underlying technology.


Choosing to use the RESTful architecture was easy. Choosing a versioning convention was not so easy. Initially we punted on the question of versioning by not versioning the beta at all. However, within a couple months the beta was in the hands of a few customers and we began building out our cloud service.  Time to version. We evaluated two versioning conventions. En first was to put the versioning directly in the URI and the second was to use an Accept header. En first option is more explicit and less complicated, which is easier for developers.  Since we love developers, it was the logical choice.


Gobernanza de las API

With a versioning convention selected we had more questions. When would we bump the version? What is a breaking change?  Would we reversion the whole API or just certain endpoints? At SparkPost, we have multiple teams working on different parts of our API. Within those teams, people work on different endpoints at different times. Therefore, it’s very important that our API is consistent in the use of conventions. This was bigger than versioning.


We established a governance group including engineers representing each team, a member of the Product Management team, and our CTO. This group is responsible for establishing, documenting, and enforcing our API conventions across all teams. An API governance Slack channel also comes in handy for lively debates on the topic.


El grupo de gobernanza identificó varias formas de introducir cambios en la API que sean beneficiosos para el usuario y no constituyan un cambio radical. Entre ellas figuran:


  • Un nuevo recurso o punto final de API

  • Un nuevo parámetro opcional

  • Modificación de un punto final de API no público

  • Una nueva clave opcional en el cuerpo JSON POST

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


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


  • Un nuevo parámetro obligatorio

  • Una nueva clave obligatoria en los cuerpos POST

  • Eliminación de un punto final existente

  • Eliminación de un punto final existente request method

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


El Gran 1.0

Mientras documentábamos y discutíamos estas convenciones, también llegamos a la conclusión de que lo mejor para todos (¡incluidos nosotros!) era evitar hacer cambios de última hora en la API, ya que la gestión de múltiples versiones añade bastante sobrecarga. Decidimos que había algunas cosas que debíamos arreglar en nuestra API antes de pasar a la "v1".


Sending a simple email required way too much effort.  To “keep the simple things simple” we updated the POST body to ensure that both simple and complex use cases are accommodated.  The new format was more future-proof as well.  Secondly we addressed a problem with the Metrics endpoint. This endpoint used a “group_by” parameter that would change the format of the GET response body such that the first key would be the value of the group by parameter. That did not seem very RESTful so we broke each group by into a separate endpoint. Finally we audited each endpoint and made minor changes here and there to ensure they conformed with the standards.


Documentación precisa

It is important to have accurate and usable API documentation to avoid breaking changes, of the deliberate or unintentional kind. We decided to use a simple API documentation approach leveraging a Markdown language called API Blueprint and gestionar nuestros documentos en Github. Our community contributes and improves upon these open source docs.  We also maintain a nonpublic set of docs in Github for internal APIs and endpoints.


Initially, we published our docs to Colmenar, a great tool for prototyping and publishing API docs. However, embedding Apiary into our website doesn’t work on mobile devices so we now use Jekyll to generate static docs instead.  Our latest Documentación de la API SparkPost now load quickly and work well on mobile devices which is important for developers who are not always sitting at their computer.


Separar el despliegue de la liberación

Aprendimos pronto el valioso truco de separar un despliegue de una publicación. De esta forma es posible desplegar con frecuencia los cambios cuando están listos a través de la entrega y el despliegue continuos, pero no siempre los anunciamos o documentamos públicamente al mismo tiempo. No es raro que despleguemos un nuevo punto final de API o una mejora de un punto final de API existente y lo utilicemos desde la interfaz de usuario o con herramientas internas antes de documentarlo públicamente y darle soporte. De este modo, podemos hacer algunos ajustes para mejorar la usabilidad o la conformidad con los estándares sin tener que preocuparnos de hacer un temido cambio de última hora. Cuando estemos satisfechos con el cambio, lo añadiremos a nuestra documentación pública.


¡Ay!

It is only fair to admit that there have been times where we have not lived up to our “no breaking changes” ideals and these are worth learning from. On one occasion we decided it would be better for users if a certain property defaulted to true instead of false. After we deployed the change we received several complaints from users since the behavior had changed unexpectedly.  We reverted the change and added an account level setting – a much more user friendly approach for sure.


De vez en cuando tenemos la tentación de introducir cambios de última hora como resultado de la corrección de errores. Sin embargo, decidimos dejar a un lado estas idiosincrasias en lugar de arriesgarnos a romper las integraciones de los clientes en aras de la coherencia.


There are rare cases where we made the serious decision to make a breaking change – such as deprecating an API resource or method – in the interest of the greater user community and only after confirming that there is little to no impact to users. For example, we deliberately made the choice to alter the response behavior of the Suppression API but only after carefully weighing the benefits and impacts a la community and carefully communicating the change to our users. However, we would never introduce a change that has a remote possibility of directly impacting the sending of a user’s production email.

Your new standard in Marketing, Pay & Sales. It's Bird

The right message -> a la right person -> en el right time.

By clicking "See Bird" you agree to Bird's Confidencialidad.

Your new standard in Marketing, Pay & Sales. It's Bird

The right message -> to the right person -> en el right time.

By clicking "See Bird" you agree to Bird's Confidencialidad.