Header Ads Widget

Ticker

6/recent/ticker-posts

Conoce a Hyrum y Postel

 


¿Cómo afectan la ley de Hyrum y la ley de Postel a los diseños de API?

Afortunadamente para nosotros los humanos, y especialmente para esa pequeña subclase de humanos que construyen API, el diseño de API es un campo que no ha sido automatizado o botificado… todavía. Claro, uno puede apuntar a un esquema de base de datos y generar lo que se puede etiquetar como "Interfaz de programación de aplicaciones". Pero es una API solo en un sentido literal, y ciertamente no en RESTful. No proporciona ninguno de los beneficios de diseñar una capa de abstracción de API, como desacoplar su API del back-end. (Consulte Cómo construir y hacer cumplir una excelente gobernanza de API de las API nórdicas ).

Una de las razones por las que el diseño de API es más un arte que una ciencia es que todavía se requiere inteligencia humana para sopesar las fuerzas en competencia que surgen. Hay numerosos libros de cocina de diseño de API disponibles, como el libro de cocina de REST API , The Design of Web API , RESTful Web API y Design and Build Great Web API . Estos recursos ofrecen varias categorías y capas de pautas de diseño que son fáciles de entender y aplicar para los humanos ... menos para una inteligencia artificial. El arte del diseño de API radica en sopesar y tomar decisiones en torno a esas compensaciones.

Considere dos principios de diseño de software centrados en el ser humano que son tan impactantes que se caracterizan mejor como leyes:

[John] Ley de Postel

Las implementaciones de TCP deben seguir un principio general de solidez: sea conservador en lo que haga, sea liberal en lo que acepte de los demás.

La Ley de Postel es tan útil que se ha generalizado fuera del ámbito estrecho de las implementaciones de TCP como el Principio de Robustez :

Sea conservador en lo que envía, sea liberal en lo que acepta.

La Ley de Postel se centra en hacer que las implementaciones de servicios sean más robustas al permitir que las interfaces y los mensajes evolucionen con el tiempo. Una buena consecuencia de la Ley de Postel es que puede hacer que las API sean más fáciles de usar, lo que veremos en un momento.

Ley de Hyrum

Con una cantidad suficiente de usuarios de una API, no importa lo que prometa en el contrato: alguien dependerá de todos los comportamientos observables de su sistema.

Si bien la Ley de Postel es una de esas barandillas que lo ayudan a diseñar API robustas, la Ley de Hyrum , acuñada por Hyrum Wright , es uno de esos acantilados de 1,000 pies a lo largo de ese estrecho y sinuoso camino de montaña de grava. Ya sabes, el que no tiene barandilla. La Ley de Hyrum es tan traicionera; incluso tiene una manifestación XKCD .

El problema que nuestros cerebros humanos pueden resolver pero los señores de los robots no pueden (todavía) es cómo sopesar a Postel contra Hyrum. Probablemente quieras algo un poco más concreto (a menos que ya hayas cruzado ese acantilado, en cuyo caso quieres algo un poco más sedoso 🪂).

Veamos algunos ejemplos.

Ejemplos de la ley de Postel en acción

Ejemplo 1 : Imagine que se le ha encomendado crear una API para que los autores envíen contenido para su publicación en el sitio de las API nórdicas. Una operación de API en su "API de envíos" acepta el número de teléfono de contacto del autor. Con la Ley de Postel en mente, diseña la API para aceptar múltiples formatos, como "(910) 555-1234""910.555.1234""9105551234"También diseña la API para que siempre devuelva números de teléfono con formato E.164 , como "+19105551234"Esta interpretación de "Sea conservador en lo que envía, sea liberal en lo que acepta" produce una API que es más fácil de usar para los clientes:

  • Los clientes pueden pasar números de teléfono en múltiples formatos según las preferencias de entrada del usuario; cada cliente no tiene que normalizar los números de teléfono.
  • Los consumidores de API no tienen que preocuparse por analizar / admitir varios formatos de números de teléfono devueltos en las respuestas de la API, solo un formato bien definido.

Ejemplo 2 : La operación de la API de envíos para buscar envíos tiene un parámetro de consulta, definido por la notación OpenAPI Specification (OAS):

parameters:
- name: published
in: query
type: boolean

La OEA se basa en el esquema JSON (consulte 7 organismos de estándares API con los que participar ) para definir los tipos de propiedades, parámetros y cuerpos de solicitud. Entonces, claramente, uno puede pasar ...?published=true...?published=falseSin embargo, algunos lenguajes de cliente no usan tokens truefalsepara valores booleanos. Python, por ejemplo, usa Truey en su Falselugar.

¿Debería uno aplicar la Ley de Postel y ser liberal en lo que la API acepta aquí, como con los números de teléfono? Puede ser tentador código de la API para aceptar ?published=True?published=TRUE?published=t, o incluso ?published=1Todas son posibles representaciones de un valor "verdadero" en varios lenguajes de programación de clientes. Su marco de implementación puede incluso tener una buena utilidad que puede convertir todo tipo de valores en valores booleanos. Sin embargo, este ejemplo y el siguiente muestran los riesgos de agregar demasiada flexibilidad en la validación de entrada.

Ejemplo 3 : El API tiene una operación que acepta una solicitud de esquema corporal con una propiedad, publicationDatePor lo tanto, una solicitud JSON válida especificaría la fecha de la siguiente manera:

{ ..., "publicationDate": "2020-12-09", ... }
Se pueden usar construcciones de esquemas OAS / JSON más elaboradas para ser más liberales en lo que permite la API, como JSON Schema oneOfanyOf, o usar en pattern: <regex>lugar de format: ...Sin embargo, tales alternativas ofuscan las API, y eso es enemigo de la claridad y la facilidad de uso. Además, no todos los lenguajes de cliente y SDK admiten oneOfanyOfesquemas.

Digamos que está en una lista de la Ley de Postel y codifica la implementación para aceptar otros formatos de fecha, como "2020/12/09""Dec 09, 2020"para la fecha 09 de diciembre de 2020, para que la API sea más fácil de usar (ignorando el hecho de que "12/09/2020"es ambiguo). Sabiendo que es fundamental validar todas las entradas del usuario en una API pública , encontrará una buena biblioteca de código abierto que analiza las fechas. Pero un año después, el equipo migra la implementación de la API a un nuevo tiempo de ejecución de lenguaje y una nueva biblioteca que también acepta estos formatos. Dichos cambios de backend no deberían afectar a los consumidores de API. Sin que usted lo sepa, algunos clientes han estado pasando fechas en "09-Dec-2020"formato. El nuevo marco y la biblioteca no manejan esto, ni admiten todos los valores "veraces" que permitiste anteriormente para el?published=parámetro de consulta. ¡La Ley de Hyrum ha golpeado!

Evolución de API

La intención original de la Ley de Postel era explicar la evolución de la interfaz. (Consulte también las API nórdicas ' ¿Cuál es la diferencia entre las API de control de versiones y revisión? ). Ejemplos de evolución en el espacio de API incluyen la adición de nuevas propiedades a un esquema JSON. Este es un principio fundamental de las API REST “buenas”: el servicio y los clientes deben tener la libertad de evolucionar (de manera compatible) de forma independiente entre sí. Por ejemplo, la primera versión de la API de publicación puede permitir pasar solo las propiedades del título y la fecha de publicación:

{
"title": "Meet Hyrum and Postel",
"publicationDate": "2020-12-09"
}

Una nueva versión del servicio puede agregar una nueva propiedad de revisión, por lo que las solicitudes pueden verse así:

{
"title": "Meet Hyrum and Postel",
"publicationDate": "2020-12-09",
"revision": "2020-10-28"
}

Un servicio robusto permitiría esta solicitud (¡incluso en la primera versión!) Ignorando (y quizás registrando) las propiedades que no reconoce, en lugar de tratarlas como un error. Los clientes que consumen dicho contenido también deben ser indulgentes con lo que reciben. Un cliente creado para la primera versión de una API no debería fallar si se conecta a la versión más reciente de la API que incluye nuevas propiedades.

Una consecuencia del diseño de API que nos dice la Ley de Postel: al definir esquemas JSON para nuestras API, evite usar additionalProperties: false¡Hacerlo golpea la puerta en la cara de John Postel!

La Ley de Hyrum establece que alguien dependerá de todos los comportamientos observables de su sistema. Esto incluye comportamientos que no se tienen en cuenta explícitamente en el diseño o la documentación de la API, como el "09-Dec-2020"formato de fecha anterior. Si uno considera que una definición de API es un contrato de software, entonces la Ley de Hyrum significa que los consumidores han encontrado (y dependen de) lagunas en ese contrato. Los veteranos de la industria están familiarizados con un cliente que ha llegado a confiar en el comportamiento con errores, del que aprenden rápidamente solo después de lanzar un parche de error.

Ley de Hyrum y evolución API

Las API deben evolucionar con el tiempo. La Ley de Hyrum nos dice que ese cambio será doloroso. Imagine que no proporcionó una definición de OpenAPI con sus primeras versiones de la API de envío, pero eligió agregarla después de varias solicitudes de los consumidores. Describe la publicationDatepropiedad de la cadena y su necesidad de representar un valor de fecha:

publicationDate:
description: The intended publication date of the submission.
type: string
format: date
example: "2020-12-09"

La ley de Hyrum también significa dolor aquí. Un diseño de API que se adhiere estrictamente a la especificación OpenAPI y la validación del esquema JSON no siempre permite la cláusula de "sea liberal en lo que acepta" de la ley de Postel.

JSON Schema nos dice que una cadena con el dateformato debe seguir el formato RFC 3339 "MMMM-DD-YY" . Es posible que los marcos y bibliotecas de API basados ​​en OAS y JSON Schema no permitan entradas que no pasen la estricta validación de JSON Schema.

En efecto, esta elección de diseño impone una restricción más estricta a la API. No se permiten otros formatos de los que los usuarios han llegado a depender. Para mantener la compatibilidad, está obligado a abandonar el uso de format: datela propiedad para mantener su parentesco con la Ley de Postel. (Con suerte, lo averigua antes de publicar la definición de la API de OEA). Pero para protegerse contra la Ley de Hyrum, debe especificar todos los formatos de fecha permitidos.

Otro ejemplo de la Ley de Hyrum causando estragos sería un cliente que aprueba:

{
"title": "NordicAPIs",
"publicationDate": "2020-12-09",
"revision": 25
}

al ejemplo de publicación anterior. Quizás porque están reutilizando una respuesta de otra API que incluye revision, y simplemente no la eliminan antes de llamar a su API de envíos. Este comportamiento se permitió en la primera versión y quizás el cliente incluso llegue a depender de este comportamiento. Sin embargo, una vez que el servicio agrega una revisionpropiedad con el tipo string, esa solicitud del cliente provocará un error en la API de Sumissions. ¡Algo tan simple como agregar una nueva propiedad puede romper a los consumidores existentes!

Desafortunadamente, hay muchas formas en las que la evolución de la API puede tener tales efectos negativos: agregar un valor a una lista de enumeración o cambiar el valor maxLengthde una cadena de 80 a 100 puede quebrar al consumidor. Incluso cambiar el código de respuesta HTTP para una llamada errónea de 400 a 422 cambiará un "comportamiento observable".

Recomiendo encarecidamente la charla de Gareth Jones, Su especificación de API no vale el papel en el que está escrita , presentada en la Cumbre de Austin de API nórdica de 2019. Gareth señala muchas formas en las que incluso pequeños cambios en las API o sus implementaciones pueden afectar a los clientes.

Equilibrar Postel y Hyrum en la práctica

Los principales impactos de las leyes de Postel y Hyrum surgen: para evitar dependencias no intencionales de datos y comportamientos no especificados, la definición de API debería hacer lo siguiente:

  1. Enumere todas las variaciones sobre cómo los desarrolladores lo usarán, como enumerar todos los formatos permitidos de todas las entradas y todas las posibles secuencias de llamadas a la API. El objetivo es convertir el contrato del software API en un "contrato férreo" y eliminar todas las lagunas.
  2. No permita ninguna entrada que se desvíe de la nueva y estricta definición de API, incluso las "inofensivas". Esto debe comenzar con la primera versión fallando explícitamente las operaciones y los datos fuera del contrato de API. Por lo tanto, ningún cliente puede llegar a depender de esos comportamientos.

Claramente, con cualquier API no trivial, ¡es imposible hacer ambas cosas! Incluso enumerar solo variaciones comunes puede agregar una hinchazón significativa a la definición de API. Desafortunadamente, las definiciones de API más grandes y detalladas son más difíciles de usar en comparación con las definiciones de API concisas. También agregan un costo significativo a la implementación, incluido el desarrollo de pruebas de regresión exhaustivas y completas. Evitar el precipicio de la ley de Hyrum está en desacuerdo con la ley de Postel de ser liberal en lo que acepta. Tratar de seguir ambos significa renunciar a las API concisas y fáciles de entender, o te bloquea en un backend que no puede evolucionar.

La mejor solución de ingeniería ingeniosa es conocer ambas leyes y sopesarlas en cada decisión de diseño de API. Una táctica es establecer expectativas razonables con sus consumidores sobre la evolución y el cambio de API. No sea un autómata cuando se trata de diseño de API. En su lugar, utilice su experiencia e inteligencia para diseñar API que respeten los límites establecidos por Hyrum y Postel y que puedan evolucionar a medida que cambien las necesidades de los consumidores de API.

Publicar un comentario

0 Comentarios