es es es es es es es es es es es es es es es es es es es zh en en es es en en en en en en en en es en en en en es my en en en en en en en en en ru my en en en en my en en en es es en ja en en es es es es es es en ca en en en en en en de en es es es en es yi en en da en en en en en my ru en en de ca en en en it en en es es en da en en da en en en da en es en de en da en en de ca en en nl en es es es es es es es es es es es es es es es es es es ar en en es ja zh zh uk ar ca es es es ca en en en en ca en en en my en en en en my en en en en my en en en en my en en en es es en en ca en en en ca en en my en en en en my en en en es en en en en sv en en en my en en en ru en my en en en es en en en en sv uk en en ru ca en tr my en en fr en my en en en en my en en en en en en en en ca fr en en en en en en en en en en en en en fi en en en en gl es zh en sv en en en en en en es en en es es es es es yi en en da en en en en en my ru en en de ca en en en it en en es en ru en ca en es en en en es uk ceb ru ru uk uk ceb ru uk ru lt ceb ru be ru kn en uk ceb uk ru lt ceb uk ru lt ceb uk ru kn en uk ceb ru ru uk uk kn en ru uk lt ceb ru ru uk uk ceb uk uk ru lt ceb uk uk ru kn en uk ceb uk uk lt ceb uk ru lt ceb uk ru kn en uk ceb ru ru uk uk kn en ru uk kn yue kn es es yi en en da en en en en en my ru en en de ca en en en en it en en es es en en en en az en nb my ru da en en en de en ca en en en en it sl ca en es en nl en en en es es en en en en az en en my ru da en en en de en ca en en en en it en ca en es en nl en en en es es fy en en en ca en en sl en de en en en en en my en uk ca en en en en it sl ru ca en en en en ja en en ca en es en en en es es es es en ceb es es es es es es es es es es es es ca es la es es es en es es es es es es fr es es es pt gl es es en es es es es es es es es es tr en es es es es es es es hu it es es en es es en es en es es es fr es
Hablando del diseño de API’s existe un principio que nos dice que todo software que se comunica con otro está acoplado de alguna manera, este acoplamiento puede ser débil o fuerte; El principio de Acoplamiento Débil del Servicio (Service Loose Coupling) descrito por Thomas Erl en su libro SOA Principles of Service Design nos dice que existen dos tipos de acoplamientos: positivos y acoplamientos negativos. Un tipo de acoplamiento positivo es aquel en el que el diseño del contrato del servicio se realiza antes de implementar la lógica interna al servicio ( aproach conocido como API First). Esto significa que yo como diseñador de API voy a poner atención principalmente en la definición del contrato sin voltear a ver en estos momentos al Backend para saber como lo vamos a implementar, esos detalles se describirán en etapas posteriores al diseño del contrato.
Entre otras ventajas, este enfoque también nos brinda el beneficio de permitirnos reemplazar la lógica del Backend de manera transparente y con un impacto prácticamente nulo de cara a aquellos que consumen el servicio, existen varios lenguajes en la industria que nos permiten definir el contrato de nuestra API REST, el lenguaje RAML es uno de ellos, nos permite enfocarnos en el diseño de nuestra API antes de implementarla.
RAML es un lenguaje de modelado para APIs RESTful, el cual básicamente nos permite escribir el contrato del API y todos sus aspectos como definir sus recursos, métodos, parámetros, respuestas, tipos de medios y otros componentes HTTP básicos. Finalmente, puede usarse también para generar documentación más amigable de cara a los consumidores del API.
Pero RAML no es el único lenguaje usado en la industria para describir API’s RESTful, también existen otros productos como Open API Swagger ambos con mucha popularidad, sin embargo existen algunas diferencias entre ambos:
La gran característica para Swagger es que está diseñado como una especificación con aproach bottom-up (pone atención principalmente en la implementación y de ahí parte para exponer el contrato) , lo contrario a RAML que es una especificación del tipo top-down.
Swagger cuenta con una gran comunidad y algunas herramientas disponibles cosa que con RAML aún no es tanto, existen pocas herramientas para RAML por lo que algunas empresas que lo usan han optado por desarrollar sus propias herramientas customizadas a las necesidades propias.
RAML se basa en otro lenguaje llamado YAML el cual es un formato de datos legible por humanos (human friendly) que se alinea bien con los objetivos de diseño de la especificación RAML. Al igual que en YAML, todos los nodos son como claves, valores y etiquetas lo cual ayuda a comprender mejor la lectura de un fichero RAML.
RAML 1.0 (versión que se describe en este artículo) es la versión más actual del lenguaje, de tal manera que son documentos compatibles con YAML 1.2 que comienzan con una línea de comentarios YAML requerida que indica la versión RAML, de la siguiente manera:
RAML usa estructuras llamadas Types para especificar el modelo de entidades a utilizar dentro del API, es un modelo sencillo de representar a las entidades y a mi parecer más fácil de utilizar que otros modelos como por ejemplo JSON Schema.
Con la palabra reservada ‘Library’ en el encabezado especificamos que estamos creando una librería en este caso que contiene el type llamado user. Aunque podemos declarar varios types en una misma librería se suele crear una librería por cada Type.
Un Type puede tener atributos sencillos como parte de su estructura o tener atributos más complejos (anidados) como en el siguiente ejemplo donde el atributo ‘status’ a su vez tiene mas atributos:
Card alias. This attribute allows customers to assign a custom name to their cards.
enum: [INOPERATIVE, BLOCKED, PENDING_EMBOSSING, PENDING_DELIVERY, PRE_ACTIVATED]
Reason of the state of the card.
RAML define diversos tipos de datos, parecidos a los que se definen en lenguajes de programación como Java:
tipos escalares: number, boolean, string, date-only, time-only, datetime-only, datetime, o integer
Los tipos se pueden clasificar respecto a los siguientes puntos:
Los tipos se clasifican dentro de 4 familias: external, object, array, y scalar.
Los ‘facets’ son configuraciones especiales, algunos de los facets permitidos son: properties, minPoperties, maxPoperties, additionalProperties, discriminator, y discriminatorValue.
Solo los objetos pueden declarar el ‘properties’ facelet.
En RAML 1.0 se permite la Herencia, por ejemplo se puede tener un Type que represente a una Persona y aparte tener a un Type Teacher que herede algunas de sus atributos de Person:
¿Cómo se modelan los recursos en RAML?
En el siguiente ejemplo vamos a modelar en REST un listado de películas y queremos definir un filtro opcional (queryParam) por el año en que salió la película, a continuación esperamos que el servidor nos conteste con un arreglo de películas que cumplen con ese criterio de búsqueda.
Técnicamente hablando definimos un recurso que se llamará /films el cual podríamos invocar de esta manera:
La declaración de ese endPoint en lenguaje RAML quedaría como:
Service for get films.
description: Filters the film by release year.
Los métodos http cuelgan de cada recurso, subrecurso o URI Parameter como se ejemplifica a continuación:
La definición de las respuestas deben venir acompañados del código http y del formato en el que vendrán los datos, generalmente las respuestas vienen en formato ‘application/json’. Se deben poner los códigos http de éxito el cual generalmente es uno 2XX así como los códigos de error, por ejemplo la invocación al endPoint puede regresar un error de tipo 404 ‘Recurso no encontrado’.
description: Get a Book by id
Ejemplo de API para gestión de películas
Para este blog a manera de ejemplo práctico vamos a modelar con RAML un API de películas que permita:
Ver un listado de películas
Filtrar por año de estreno.
Ver información detallada de la película como la duración, el genero, el año de estreno o el ranking de calificación de los usuarios.
Listar  los directores que intervienen.
Listar los actores que intervienen.
Listar los personajes dentro de la película.
Listar las imágenes asociadas a un película (por ejemplo una imagen pequeña para mostrarse en un listado y una imagen grande para mostrase en un detalle).
Poder ver el detalle de un personaje de la película.
Dar de alta una nueva película.
De tal forma que se van a generar los siguientes endPoints:
El modelo de datos detrás de un API puede especificarse mediante cualquier lenguaje de modelado de datos conceptual como por ejemplo un modelo de entidad-relación simple o con los clásicos diagramas de clase UML.
En este ejemplo utilizaremos un modelo entidad-relación para representar de manera gráfica la relación entre las entidades identificadas así como la definición de sus atributos.
Modelo de types de películas en RAML
En este caso lo primero que vamos a definir en RAML son los Types que representan al modelo de lo cuales obtendremos los siguientes archivos:
Cabe destacar que vamos a generar un Type que usaremos para representar el listado de un recurso y otro Type que represente el detalle del recurso (lo hacemos así porque para un listado solo vamos a mostrar algunos atributos y para el detalle otros), para el listado se nombrará al Type en plural. Por ejemplo tenemos un Type ‘film.raml’ que usaremos para mostrar los atributos de una película en un detalle y el Type ‘films.raml’ para mostrar los atributos de la película en el listado.
A continuación describiremos algunos de los types identificados (la lista completa se puede encontrar el el repositorio de GitHub anexo a este artículo).
Person second last name.
A continuación definiremos la entidad que representa a un actor el cual hereda algunas de sus propiedades de person.
Podemos hacer uso del nodo ‘uses’ para importar librerías externas, en este caso vamos a exportar la entidad ‘person’:
A continuación la definición del Type que representa al genero de la película, aquí podemos ver que hacemos uso de la estructura ‘enum’ el cual nos permite delimitar los posibles valores del genero:
Y a continuación la representación de un listado de películas:
Definir los recursos del API de películas
Para hacer la definición de los recursos de nuestra API la haremos en un archivo llamado ‘api.raml’ donde estarán definidos todos los recursos del API. Para comenzar describiremos la sección de los encabezados y la importación de los types.
Ahora vamos a modelar la siguiente funcionalidad con RAML:
Vamos a definir un recurso REST llamado ‘/films’ que gestione las operaciones a realizar sobre las películas.
Vamos a definir un método GET para poder obtener un listado de películas.
Vamos a definir un ‘queryParameter’ llamado ‘year’ con el cual vamos a poder listar las películas filtradas con una fecha de lanzamiento dada.
Service for get films.
description: Filters the film by release year.
Las partes importantes de la definición del bloque anterior es que en la respuesta vamos a modelar que se espera que el servicio regrese la información en notación JSON dentro de un nodo llamado data el cual es de tipo array y cada elemento del array regresará la información de cada película como se ve en el siguiente ejemplo JSON:
«name»: «The Lord of the Rings: The Return of King»,
«size»: «20 x 15»
«size»: «20 x 15»
Definiendo ejemplos JSON en el API
Se pueden definir ejemplos JSON para ayudarle al consumidor del API a darse una idea de la información que regresará el endPoint como se ve a continuación. El archivo llamado ‘get_200.json’ contiene el ejemplo de los datos regresados por el endPoint:
Service for get films.
description: Filters the film by release year.
Obtener el detalle de una película
Ahora vamos a definir el URI parameter para poder obtener el detalle de una película, las llaves {} alrededor del nombre del parámetro son los que nos indican la declaración del URI parameter. La declaración se hace de esta manera:
Manages the information of a specific Film.
description: «Unique film identifier»
Service for retrieving the information associated to a specific film.
Poder ver el detalle de un personaje dentro de la película
A continuación veremos el fragmento donde se declara la sección para poder ver el detalle de un personaje de la película:
Manages the information of a specific Character.
description: «Unique character identifier»
Service for retrieving the information associated to a specific character.
Crear una película nueva
El siguiente fragmento muestra como crear una nueva película:
Service to create a new Film.
description: This header must provide the URI to reach the created resource.
En el ejemplo mostrado en el fragmento anterior (a diferencia de los métodos GET) para métodos POST se tiene que enviar un payload de entrada además de que también el endPoint regresará un encabezado http llamado ‘Location’ con la ubicación del recurso recién creado.
Este artículo habla de la introducción al lenguaje para modelar API’s REST llamado RAML (RESTful API Modeling Language), se describieron algunas sintaxis básicas del lenguaje, además se demostró su uso con un ejemplo práctico para un API de gestión de películas. El código completo de este ejemplo se puede descargar desde mi GitHub el cual está disponible aquí.
En una próxima entrega describiré sintaxis más complejas del lenguaje RAML como es el uso de traits, resource-types y custom-anotations, features que nos van a permitir escribir código RAML de manera más eficiente y reutilizable. También en futuras entregas hablaré de una herramienta que nos permitirá diseñar nuestras API’s RAML de manera gráfica. Por el momento les dejo estas dos referencias de herramientas para editar API’s RESTful usando RAML:
Para escribir el código de este ejemplo lo he hecho usando Sublime usando el Plugin para RAML y me ha resultado bastante útil, más adelante veremos que existen herramientas más amigables para la edición de nuestro código de momento nos va bien hacerlo en este editor.
También dejo el link con referencia a la especificación del lenguaje en su versión 1.0 la más actual.