
Olá% username%!
Você provavelmente sabe o que são APIs e quanto depende delas em seu projeto. Além disso, também acredito que você já está familiarizado com a
primeira abordagem da
API e sabe que o
Swagger e sua
API aberta são algumas das ferramentas mais populares para ajudá-lo a seguir.
Mas neste artigo, quero falar primeiro sobre a abordagem da implementação da API, conceitualmente diferente da que o Swagger e o Apiary oferecem. Na cabeça da idéia está o conceito de
contrato único e a possibilidade de sua implementação com base no RAML 1.0.
Sob o corte:
- Uma breve descrição dos princípios da API primeiro;
- Contrato único - introdução de um conceito, pré-requisitos para a aparência, consideração da possibilidade de sua implementação com base na OEA (Swagger);
- RAML + anotações + sobreposições como base para contrato único , exemplos;
- Problemas de RAML, desacordos conceituais dos desenvolvedores;
- A idéia de um serviço SaaS baseado na idéia acima (imagem do protótipo acima).
Da API primeiro no Swagger ao contrato único no RAML
Ao projetar sistemas de software modernos, muitas vezes surge a tarefa de coordenar e desenvolver interfaces para a interação de seus componentes. Na última década, o SPA e aplicativos móveis espessos que interagem com o servidor por meio de APIs ganharam imensa popularidade e desenvolvimento. Anteriormente, o desenvolvimento de um site interativo era realizado pela edição estágio a estágio do código do servidor para gerar a marcação HTML com sua subsequente transferência para o navegador do cliente. Agora, o desenvolvimento de aplicativos dinâmicos da Web mudou para a criação de uma API de serviço único e o desenvolvimento paralelo de muitos aplicativos (incluindo SPA) funcionando. com essa API como a principal fonte de dados. Essa abordagem permite compartilhar tarefas de forma mais conveniente, organizar equipes especializadas apenas em tecnologias específicas (atrair especialistas mais especializados), organizar o desenvolvimento paralelo nos primeiros estágios e também criar um único ponto de comunicação - uma interface API.
Esse ponto único de comunicação requer uma definição formal e inequívoca; este documento é uma especificação da API. Atualmente, para desenvolver e documentar as especificações da API, são usadas várias tecnologias e linguagens, por exemplo: OEA (Swagger), Apiary e RAML.
Os três pontos a seguir determinam a natureza da primeira abordagem da API:
- A API deve ser a primeira interface do cliente do aplicativo desenvolvido;
- Primeiro de tudo, uma especificação de API é desenvolvida e, em seguida, o software faz parte de seus clientes;
- Os estágios de vida de uma API devem coincidir com os estágios de vida de sua documentação.
Se considerarmos o processo com base no exposto acima, a especificação da API estará no centro do processo de desenvolvimento, e todos os nós que compõem o sistema e usam essa API como um gateway de interação são clientes da especificação da API. Portanto, a parte do servidor do sistema pode ser considerada a mesma API de especificação do cliente, como qualquer outro nó que usa a API para se comunicar com ele. Os modelos de domínio do aplicativo não precisam corresponder aos modelos descritos na especificação da API. Suas possíveis coincidências intencionais com estruturas de classe no código de aplicativo cliente ou com estruturas de esquema de banco de dados são introduzidas para simplificar o processo de desenvolvimento, por exemplo, ao usar um gerador de código de acordo com a especificação da OEA. Logicamente, o acima pode ser resumido sob a definição de
contrato único .
Contrato único - muitos clientes.
Contrato único. Ferramentas e bibliotecas de contrato
O termo contrato único não reivindica nenhuma participação em críticas por seu uso no texto do artigo. Sua aplicação, nesse contexto, é pessoalmente minha ideia.
Estender o conceito de
API primeiro a um
contrato único mais geral nos permite considerar a especificação da API não apenas como uma descrição formal da interface entre os componentes do sistema, mas também como um
contrato único usado por qualquer número de bibliotecas e ferramentas externas como fonte de configuração. Nesse caso, essas ferramentas e bibliotecas podem ser percebidas como clientes contratados, juntamente com SPA ou aplicativos móveis. Exemplos de tais clientes incluem:
- Gerador de documentação
- API do servidor simulado
- Serviço de teste de estresse
- Biblioteca de validação de solicitação / resposta
- Gerador de código
- Gerador de UI
- etc.
Contrato único para esses clientes é um único arquivo de configuração e fonte de dados. Os instrumentos contratuais funcionam apenas com base nas informações obtidas de um contrato específico. Obviamente, para a funcionalidade completa de clientes heterogêneos como o servidor de simulação da API, uma descrição da API não é suficiente, são necessárias metinformações adicionais, por exemplo, uma descrição do relacionamento entre os parâmetros de solicitação GET (ID do recurso) e os dados que o servidor deve retornar, dicas apontando para os campos de resposta e parâmetros de consulta usados para organizar a paginação. Além disso, este exemplo será considerado em mais detalhes. Informações específicas para instrumentos específicos, ao mesmo tempo, devem existir e ser mantidas inextricavelmente a partir do documento principal; caso contrário, isso violará o conceito de um único contrato.
Swagger (OEA) como ferramenta de descrição de contrato único
O Swagger (OEA) e o Apiário (Blueprint) mais populares existentes no mercado permitem que você descreva APIs HTTP usando linguagens especiais: API aberta com base em YAML ou JSON, Blueprint com base em Markdown, o que facilita a leitura das especificações. Existem também muitas ferramentas e bibliotecas criadas pela grande comunidade de código aberto. Atualmente, o Swagger é amplamente distribuído e, pode-se dizer, tornou-se o padrão de fato da API primeiro. Muitos sistemas externos suportam a importação de especificações Swagger, como
SoapUI ,
Readme.io ,
Apigee , etc. Além disso, o SaaS
Swagger Hub e o
Apiary existentes permitem que os usuários criem projetos, carreguem ou criem suas próprias especificações, usem os geradores de documentação e servidores de simulação incorporados, bem como publiquem links para acessá-los de fora.
O Swagger, juntamente com o OEA 3.0, parece bastante confiante e sua funcionalidade para descrever a API (especialmente simples) é suficiente na maioria dos casos. A seguir, é apresentada uma lista dos prós e contras do Swagger:
Prós:
- Linguagem de descrição clara e fácil de ler;
- Grande comunidade de código aberto;
- Muitos editores oficiais e de código aberto, geradores, bibliotecas;
- A presença de uma equipe de desenvolvimento central trabalhando constantemente no desenvolvimento e aprimoramento do formato;
- Hub Shareware para especificações;
- Documentação oficial detalhada;
- Baixo limiar de entrada.
Contras:
- Suporte de modularidade fraco;
- Falta de exemplos gerados automaticamente de respostas a consultas com base na descrição de suas estruturas;
- Muitas vezes, existem problemas com a baixa estabilidade dos produtos SmartBear (autores do swagger) e a reação tardia do desenvolvedor a isso (a opinião é baseada puramente na experiência pessoal de uso e na experiência de nossa equipe).
Porém, a principal limitação que não permite o uso da OEA como meio de descrever
um contrato único é a falta de capacidade de anexar meta-informações personalizadas para descrever parâmetros adicionais de ferramentas / bibliotecas-alvo.
Portanto, todas as ferramentas que funcionam com base nas especificações do Swagger devem estar satisfeitas com o conjunto de informações que podem acomodar o formato básico.
Por exemplo, a implementação de um servidor de API simulada inteligente requer mais informações do que um documento de especificação pode fornecer, e é por isso que a API simulada integrada do Swagger Hub é capaz de gerar dados falsos apenas com base em tipos / estruturas de dados obtidos de um documento de especificação. Sem dúvida, isso não é suficiente e uma funcionalidade de servidor de simulação pode ser satisfeita apenas por um simples cliente de API.
Em nossa empresa, durante o desenvolvimento de um dos projetos (servidor React SPA + API), foi necessária a seguinte funcionalidade de servidor de simulação:
- imitação de paginação. O servidor não deve retornar valores completamente aleatórios dos campos currentPage, nextPage, pagesTotal em resposta a solicitações de lista, mas simular o comportamento real do mecanismo de paginação com a geração dos valores dessas metapoles, dependendo do valor da página recebida do cliente;
- gerar corpos de resposta contendo vários conjuntos de dados, dependendo do parâmetro específico da solicitação recebida;
- a capacidade de criar relacionamentos reais entre objetos falsos: o campo foo_id da entidade Bar deve se referir à entidade Foo gerada anteriormente. Isso pode ser alcançado adicionando suporte à idempotência no servidor simulado;
- imitação do trabalho de vários métodos de autorização: OAuth2, JWT etc.
Sem tudo isso, é muito difícil desenvolver o SPA em paralelo com o desenvolvimento da parte do servidor do sistema. E, ao mesmo tempo, é quase impossível implementar um servidor tão falso, pelo motivo descrito acima, sem meta informações específicas adicionais que possam ser armazenadas diretamente na especificação da API e informá-lo do comportamento necessário ao simular o próximo terminal. Esse problema pode ser resolvido com a adição dos parâmetros necessários na forma de um arquivo separado, com configurações paralelas à especificação básica da OEA, mas, nesse caso, você precisa apoiar essas duas fontes diferentes separadamente.
Se houver mais de um servidor simulado com ferramentas trabalhando no ambiente do processo de desenvolvimento de acordo com esse princípio, obteremos um "zoológico" de ferramentas, cada uma das quais, com sua própria funcionalidade exclusiva, é forçada a ter seu próprio arquivo de configuração exclusivo, logicamente vinculado à API base -especificações, mas na verdade localizadas separadamente e vivendo “a própria vida”.

Problema: o desenvolvedor será forçado a manter a relevância de todas as configurações após alterar as versões da especificação base, geralmente em locais e formatos completamente diferentes.
Alguns exemplos de serviços que funcionam com um princípio semelhante:
- O SoapUI é um sistema para testar interfaces REST e SOAP. Suporta a importação de um projeto da especificação Swagger. Ao alterar a especificação básica do Swagger, a configuração de um projeto com base em uma lista de chamadas de API continua a existir em paralelo e requer sincronização manual;
- Outros produtos SmartBear ;
- Apigee é um serviço de gerenciamento de ciclo de vida da API. Ele usa as especificações Swagger como modelos, com base nos quais permite inicializar suas configurações de serviços internos. Também não há sincronização automática;
- O Readme.io é um serviço que permite criar uma documentação bonita com base na especificação Swagger e também possui um mecanismo para rastrear alterações na especificação básica e resolver conflitos, atualizando a configuração do projeto no lado do serviço. Certamente, isso exigia complexidade desnecessária no desenvolvimento desse serviço.
Você pode adicionar muitos outros serviços a esta lista que fornecem a função de integração com a especificação Swagger. A integração para a maioria deles significa a cópia usual da estrutura básica da especificação Swagger e o preenchimento automático subseqüente dos campos de configuração local sem suportar a sincronização com alterações na especificação básica.
RAML, anotações, sobreposições
O desejo de encontrar uma ferramenta que exclua a restrição da OEA mencionada anteriormente, permitindo considerar a especificação como um contrato único para todas as ferramentas clientes, levou-nos a familiarizar-nos com a linguagem RAML. Há bastante escrito sobre RAML, você pode lê-lo, por exemplo, aqui
https://www.infoq.com/articles/power-of-raml . Os desenvolvedores de RAML tentaram estabelecer o suporte à linguagem para modularidade no nível de seu conceito. Agora, cada empresa ou desenvolvedor individual pode criar seus próprios ou usar dicionários públicos prontos ao projetar a API, redefinir e herdar modelos de dados prontos. A partir da versão 1.0, o RAML suporta 5 tipos diferentes de módulos externos:
biblioteca, extensão, característica, sobreposição , o que permite que cada um deles seja usado da maneira mais flexível possível, dependendo da tarefa.
Chegou a hora de discutir a principal possibilidade do RAML, que, por razões que não são completamente compreendidas, não possui análogos na OEA e no Blueprint - Annotations.
Anotações em RAML é a capacidade de anexar metadados personalizados às estruturas de linguagem subjacentes.
Foi essa função RAML que se tornou o motivo para escrever este artigo.
Um exemplo:
#%RAML 1.0 title: Example API mediaType: application/json # Annotation types block may be placed into external file annotationTypes: validation-rules: description: | Describes strict validation rules for the model properties. Can be used by validation library allowedTargets: [ TypeDeclaration ] type: string[] info-tip: description: | Can be used by Documentation generator for showing tips allowedTargets: [ Method, DocumentationItem, TypeDeclaration ] type: string condition: description: | Named example can be returned if condition is evaluated to true. Can be used by Intelligent mock server allowedTargets: [ Example ] type: string types: Article: type: object properties: id: type: integer title: string paragraphs: Paragraph[] createdAt: type: string (validation-rules): ["regex:/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?Z?/"] Paragraph: type: object properties: order: type: integer (validation-rules): ["min:0"] content: string (validation-rules): ["max-length:1024"] /articles/{articleId}: get: (info-tip): This endpoint is deprecated description: Returns Article object by ID responses: 200: body: application/json: type: Article
As estruturas de anotação do usuário devem ter descrições claras na RAML. Para isso, é usada uma seção especial
annotationTypes , cujas definições também podem ser retiradas para o módulo externo. Assim, torna-se possível definir parâmetros especiais de uma ferramenta externa na forma de anotações anexadas à definição base da API RAML. Para evitar sobrecarregar a especificação básica com um grande número de anotações para várias ferramentas externas, há suporte para a possibilidade de transferi-las para arquivos separados -
sobreposições (e também
extensões ), com classificação por escopo. Aqui está o que é dito sobre sobreposições na documentação da RAML (
https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md#overlays ):
Uma sobreposição adiciona ou substitui nós de uma definição de API RAML, preservando seus aspectos funcionais e comportamentais. Certos nós de uma definição de API RAML especificam o comportamento de uma API: seus recursos, métodos, parâmetros, corpos, respostas e assim por diante. Esses nós não podem ser alterados aplicando uma sobreposição. Por outro lado, outros nós, como descrições ou anotações, abordam preocupações além da interface funcional, como a documentação descritiva orientada para o homem em algum idioma ou informações de implementação ou verificação para uso em ferramentas automatizadas. Esses nós podem ser alterados aplicando uma sobreposição.
As sobreposições são particularmente importantes para separar a interface da implementação. As sobreposições permitem ciclos de vida separados para os aspectos comportamentais da API que precisam ser controlados com força, como um contrato entre o provedor da API e seus consumidores, versus aqueles que precisam de pouco controle, como os aspectos orientados para a implementação ou humanos que podem evoluir em ritmos diferentes. Por exemplo, adicionar ganchos para ferramentas de teste e monitoramento, anexar metadados relevantes a um registro de APIs ou fornecer documentação humana atualizada ou traduzida podem ser obtidos sem alterar nenhum aspecto dos aspectos comportamentais da API. Essas coisas podem ser controladas através de uma versão rigorosa e do processo de gerenciamento de mudanças.
Em outras palavras, essa funcionalidade permite "separar a granulação do joio", por exemplo, a descrição principal da especificação da API, de meta-informações adicionais específicas a uma ferramenta específica que a utiliza para o trabalho. As meta-informações em cada sobreposição separada são “suspensas” em vários blocos da especificação na forma de anotações.
Um exemplo de uma estrutura básica:
#%RAML 1.0 title: Phrases API mediaType: application/json types: Phrase: type: object properties: content: string /phrases: get: queryParameters: whoSaid: string responses: 200: body: application/json: type: Phrase
Sobreposição:
#%RAML 1.0 Overlay usage: Applies annotations for Intelligent mock server extends: example_for_article_2_1.raml annotationTypes: condition: description: | Named example can be returned if condition is evaluated to true type: string allowedTargets: Example /phrases: get: responses: 200: body: application/json: examples: firstExample: (condition): $whoSaid is Hamlet content: "To be, or not to be?" secondExample: (condition): $whoSaid is Homer Simpson content: "D'oh!"
Como resultado, torna-se possível implementar um único contrato: todas as informações funcionais, comportamentais e meta-informações são armazenadas e versionadas em um único local, e as ferramentas de contrato - clientes do contrato, devem ter suporte para as anotações usadas nesta especificação. Por outro lado, são as próprias ferramentas que podem apresentar seus próprios requisitos para anotações, que devem ser "penduradas" na especificação - isso fornecerá uma gama mais ampla de possibilidades ao desenvolver ferramentas de contrato.
O conceito acima está representado na figura abaixo:

Entre as desvantagens dessa abordagem, pode-se destacar a alta complexidade da sincronização manual do arquivo de especificação base e cada uma das sobreposições: ao atualizar a estrutura da especificação básica, é necessário aplicar as alterações necessárias nas estruturas das sobreposições. Esse problema se torna mais sério quando mais de uma sobreposição aparece.
Uma solução possível e mais óbvia seria desenvolver um editor ou complemento especial para o editor de RAML online existente
https://github.com/mulesoft/api-designer . A área de edição permanece inalterada, mas torna-se possível criar guias: cada nova guia é uma janela para editar a sobreposição atribuída a ela. Ao editar a estrutura básica da especificação na janela principal, as estruturas em todas as guias criadas também mudam e, quando uma incompatibilidade da nova estrutura com as anotações existentes localizadas nas sobreposições de guias é detectada, um aviso é exibido. Uma consideração mais detalhada desse editor é um tópico separado e merece consideração séria.
Desenvolvimentos existentes
Na busca de soluções existentes que estão próximas de realizar a idéia de usar anotações como um meio de descrever as meta-informações, foram encontradas as seguintes soluções:
- https://github.com/raml-org/raml-annotations repositório contendo anotações oficiais aprovadas pela comunidade de desenvolvedores da RAML. Na versão atual, apenas as anotações do OAuth2 estão disponíveis. Eles podem ser usados por ferramentas externas para obter meta-informações que descrevem aspectos da implementação do OAuth2 para a especificação da API desenvolvida;
- https://github.com/petrochenko-pavel-a/raml-annotations biblioteca de anotações do usuário @ petrochenko-pavel-a com um agrupamento lógico por área de aplicação. O projeto é mais experimental, mas ilustra perfeitamente a ideia de usar anotações. Os grupos de anotações mais interessantes:
- additionalValidation.raml - anotações para descrever regras adicionais para a validação de modelos de especificação. Eles podem ser usados, por exemplo, pela biblioteca do servidor para validar consultas de acordo com a especificação RAML;
- mock.raml - anotações para descrever os detalhes do servidor simulado com base na especificação RAML;
- semanticContexts.raml - anotações apontando para o contexto semântico dos blocos estruturais declarados individuais da especificação RAML;
- estrutural.raml - anotações que esclarecem o papel de uma entidade RAML separada na estrutura geral do modelo de domínio descrito;
- uiCore.raml - um exemplo de anotações possíveis para uso pelas ferramentas de geração de UI com base na especificação RAML;
O repositório também contém bibliotecas de tipos de utilitários adequados para uso como primitivos na descrição de estruturas de dados da especificação RAML.
Problemas de RAML
Apesar da funcionalidade, progressividade da idéia básica e atenção dos grandes fabricantes de software (Cisco, Spotify, VMware etc.), a RAML hoje tem sérios problemas que podem se tornar fatais em relação ao seu destino de sucesso:
- Comunidade de código aberto pequena e fragmentada;
- Uma estratégia incompreensível do principal desenvolvedor de RAML é a mulesoft . A empresa desenvolve produtos que são apenas uma cópia das soluções existentes da OEA (incluídas na plataforma Anypoint ), em vez de criar serviços que enfatizam as vantagens da RAML sobre a Swagger;
- A conseqüência do primeiro parágrafo: um pequeno número de bibliotecas / ferramentas de código aberto;
- Limiar de entrada mais alto que o da OEA (isso é estranho, mas muitas pessoas pensam assim);
- Devido ao grande número de bugs e problemas com o UX / UI, o serviço principal que é completamente inadequado e repelente aos usuários é o ponto de entrada para RAML - https://anypoint.mulesoft.com/ .
Desacordo conceitual. Primeira conclusão
Existem contradições na comunidade em relação ao conceito básico. Alguém pensa que RAML é uma
linguagem de definição de modelo e alguém pensa que é uma
linguagem de definição de API como OEA ou Blueprint (os caras que se chamam desenvolvedores de RAML costumam mencionar isso em vários comentários). O conceito de
linguagem de definição de
modelo permitiria, dentro da especificação RAML, descrever o modelo de domínio do domínio sem uma ligação estreita ao contexto da descrição do recurso da API, expandindo os horizontes das opções para o uso da especificação com ferramentas externas (de fato, criando a base para a existência deste
contrato único !). Aqui está uma definição do conceito de recurso que pode ser vista no site readhat docs (
http://restful-api-design.readthedocs.io/en/latest/resources.html , a propósito, recomendo a todos que leiam este maravilhoso guia sobre design de API):
Chamamos informações que descrevem os tipos de recursos disponíveis, seu comportamento e relacionamentos como modelo de recursos de uma API . O modelo de recursos pode ser visualizado como o mapeamento RESTful do modelo de dados do aplicativo .
No
modelo de dados do aplicativo RAML
, esses são os tipos declarados no bloco de
tipos , e o
modelo de recurso de uma API é o que é descrito no bloco de RAML de
recursos . Portanto, você deve ter a capacidade de descrever esse
mapeamento . Mas a implementação atual da RAML permite que esse
mapeamento seja feito apenas 1 a 1, ou seja, use os tipos "como estão" dentro da declaração da API do recurso.
Acho que esse é o principal problema da linguagem, cuja solução permitirá que a RAML vá além da
linguagem de definição da
API e se torne uma
linguagem de definição de modelo completa: uma linguagem mais geral (em vez da OEA ou Blueprint) usada para descrever os contratos únicos de sistemas, que são essencialmente o núcleo formal muitos de seus componentes.
A descrição acima faz do RAML um jogador fraco que atualmente não consegue vencer a competição contra o Swagger. Talvez por isso, como resultado, o principal desenvolvedor da RAML tomou medidas drásticas
https://blogs.mulesoft.com/dev/api-dev/open-api-raml-better-together/A idéia do contrato único RAML SaaS
Com base no conceito de
contrato único , partindo da idéia de hospedar uma API de especificações Swagger baseada na OEA, além de contar com a possibilidade de a RAML declarar meta-informações e compartilhar a especificação básica usando sobreposições, a idéia de uma solução SaaS alternativa para hospedar e gerenciar especificações com base na linguagem RAML sugere Supere o Swagger Hub e o Apiary no volume e na qualidade da funcionalidade possível.
O novo serviço, por analogia com o hub Swagger, será a hospedagem de contratos de usuário com o fornecimento de um editor on-line e a capacidade de visualizar visualizações de documentação com atualizações em tempo real. A principal diferença deve ser a presença de um catálogo de plug-ins de contrato embutidos no serviço, dos quais o usuário poderá instalar as especificações da API em seu projeto atual. Para instalação, será necessário implementar as anotações RAML necessárias especificadas na documentação do plug-in. Após adicionar um novo plug-in ao projeto, uma nova guia será adicionada na janela do editor de código quando você alternar para ele, as anotações de edição do plug-in instalado ficarão disponíveis. A estrutura da especificação básica deve ser duplicada automaticamente em todas as guias correspondentes aos plugins. Se surgirem conflitos entre a estrutura básica e as anotações já existentes, um mecanismo especial deve oferecer opções para sua solução ou resolvê-la automaticamente.

Tecnicamente, cada guia será uma abstração da sobreposição de RAML contendo anotações de cada plug-in específico. Isso garante que a especificação seja compatível com qualquer ferramenta que suporte o RAML 1.0.
O diretório do plug-in deve estar aberto para expansão pela comunidade de código aberto. A implementação de plug-ins pagos também é possível, o que pode servir de incentivo ao desenvolvimento de novos.
Possíveis plug-ins: documentação da API com suporte para um grande número de anotações para parametrização flexível de sua renderização, servidor simulado "inteligente" (do exemplo acima), bibliotecas para download para validação de solicitações ou geração de código, ferramentas de depuração para solicitações de saída da API para aplicativos móveis (proxy de cache), testes de carga com a configuração do teste de fluxo por meio de anotações, vários plugins para integração com serviços externos.
Essa idéia do serviço contém vantagens claras sobre os serviços existentes para o gerenciamento de especificações da API, e sua implementação abre caminho para uma possível mudança na abordagem da implementação de qualquer sistema externo que esteja de alguma forma relacionado à API.
Segunda conclusão
O objetivo deste artigo não é criticar o Swagger, Apiary ou outras ferramentas padrão de fato para o desenvolvimento de APIs, mas examinar a diferença conceitual com a abordagem das especificações de design promovida pela RAML, tentar introduzir o conceito de
Contrato primeiro e considerar a possibilidade de sua implementação com base na RAML. Outro objetivo era o desejo de atrair a merecida atenção dos desenvolvedores para o RAML para o desenvolvimento possível da sua comunidade.
Site oficial RAMLCanal frouxoEspecificaçãoObrigado pela atenção.