Num
post anterior
, falamos sobre como e por que fazemos na Ancronis anotações para microsserviços e prometemos compartilhar nossa prática de usar um único formato de API para toda a Acronis Cyber Platform. Hoje, contaremos sobre a nossa experiência em verificações de anotações estáticas - também conhecido como o primeiro passo no caminho para introduzir anotações em uma empresa.

Portanto, suponha que você já tenha anotações para todas ou a maioria das APIs. Uma pergunta razoável que nossos colegas também nos fizeram: "O que pode ser feito com esses objetos mágicos?"
De fato, existem dois tipos de verificações que podem ser feitas diretamente por anotação. As verificações estáticas vão diretamente para os textos das anotações Swagger ou RAML. Eles não precisam de mais nada e podem ser considerados, com razão, a primeira vantagem do uso de contratos de microsserviço formalizados.
As verificações dinâmicas só podem ser iniciadas se você tiver um serviço em funcionamento. Eles são um pouco mais complicados, pois permitem aprofundar e verificar a validade da anotação, testar a estabilidade do serviço e também fazer muito mais. Mas este é o tópico do próximo post, e hoje vamos nos concentrar nas estáticas.
Viva a Diretriz da API!
Para não confundir você ou outras pessoas, vale a pena mencionar imediatamente que as verificações de anotação estática são criadas para controlar a conformidade das anotações da API (e, esperamos, as próprias APIs) com os requisitos corporativos. Pode ser apenas práticas adotadas pela empresa ou uma API de diretrizes completa, que formaliza as regras para preparar a API para seus serviços.

Quando falamos sobre o mundo colorido dos microsserviços, isso é muito importante, porque cada equipe pode ter sua própria estrutura, sua própria linguagem de programação, uma pilha única ou algumas bibliotecas especiais. Sob a influência de práticas específicas ao microsserviço, a apresentação da API para um observador externo está mudando. Isso cria variedade desnecessária. Para uma interação eficaz dos elementos de um ecossistema (ou plataforma), é necessário "alinhar" a API o máximo possível.
Aqui está um exemplo: o código 404 será retornado para a API de um componente apenas se o recurso não existir. E a outra equipe vincula esse erro à lógica do aplicativo e a API retornará 404 quando o usuário desejar comprar um produto que foi encerrado no armazém.
Atygaev descreveu esses problemas muito claramente
aqui . Essa inconsistência no entendimento do código 404 atrasará o desenvolvimento e levará a erros, o que significa chamadas desnecessárias para suporte ou horas extras de depuração, mas, em qualquer caso, problemas medidos em termos monetários.
As especificidades de sintaxe e nomeação adotadas pela empresa são complementadas por vários aspectos específicos do próprio REST. O desenvolvedor deve responder a perguntas como:
- O POST será idempotente ou não?
- Quais códigos de erro usamos e o que eles significam?
- Posso adicionar lógica de negócios a códigos de erro?
Agora imagine que cada equipe deva individualmente confundir essas respostas.
O formato da consulta de pesquisa também pode ser completamente diferente. Por exemplo, existem cerca de uma dúzia de maneiras de criar uma amostra na qual apenas os usuários que possuem o MacBookPro e ataques de vírus frequentes serão listados. Ao trabalhar em um grande projeto que consiste em dezenas de microsserviços, é necessário que a sintaxe da consulta de pesquisa seja comum a todas as versões e produtos da empresa. E se uma pessoa está acostumada a se referir a um dos produtos / serviços do seu desenvolvimento, ela espera encontrar a mesma estrutura de solicitação e resposta em outra. Caso contrário, a surpresa (e a dor) não serão evitadas.
Muitas empresas, especialmente gigantes, como
Microsoft ,
PayPal ,
Google , têm suas próprias diretrizes e são muito bem pensadas. Mas nem sempre é possível usar as diretrizes de outras pessoas, porque elas estão amplamente ligadas às especificidades da empresa. Além disso, o pensamento de todos tem uma estrutura diferente, e as regras podem diferir simplesmente porque é mais conveniente que as pessoas trabalhem dessa maneira e não de outra maneira.
O entendimento de que a Acronis precisa de sua própria diretriz de API não veio imediatamente, mas com o crescente número de desenvolvedores, microsserviços e clientes e integrações realmente externos. Em algum momento, a equipe de arquitetos teve que estabelecer regras uniformes para declarar a API, levando em conta a experiência dos gigantes de TI mencionados acima e as práticas de fato já estabelecidas nas equipes de desenvolvimento.
Um dos problemas com essa implementação tardia da API de diretrizes são as APIs publicadas existentes que não atendem aos requisitos, o que por sua vez leva a custos adicionais para redesenhar as interfaces e manter a compatibilidade com versões anteriores. Portanto, se seu modelo de negócios envolver integração e publicação futura da API, será necessário pensar em regras uniformes o mais cedo possível.

Obviamente, a adoção das APIs das diretrizes não tornou automaticamente todas as APIs constitutivas. Cada API precisava ser analisada, cada devlid precisava entender novos requisitos. Portanto, fizemos a automação das verificações de RAML contra a API Guideline que desenvolvemos.
Análise estática
Primeiro, você precisa decidir o que analisaremos estaticamente. Nem todos os pontos da API de diretrizes podem ser formalizados; portanto, primeiro você precisa destacar um conjunto de regras que podem ser facilmente entendidas a partir da anotação da API.
Na primeira versão, identificamos as seguintes regras:
- Verifique as descrições da API. Como dissemos no artigo anterior, você pode criar uma documentação bonita com base na anotação da API. Isso significa que cada recurso, parâmetro de consulta e resposta deve ter uma descrição que forneça todas as informações necessárias para qualquer usuário de nossa API. Parece um pouco, mas como é fácil mostrar aos desenvolvedores que suas anotações não são ricas em descrições!
- Verificando a presença e a correção dos exemplos. As linguagens de anotação da API também permitem descrever exemplos. Por exemplo, em resposta, podemos adicionar um exemplo de resposta de serviço real, algo da vida real. O uso de exemplos informa como o terminal deve ser usado e funcionando, e verificamos exemplos através da análise estática de anotações.
- Validação de códigos de resposta HTTP. O padrão HTTP define um grande número de códigos, mas eles podem ser interpretados de maneiras diferentes. Nossa diretriz formaliza o uso de códigos. Também limitamos a aplicabilidade de códigos diferentes de acordo com o método HTTP. Por exemplo, o código 201, de acordo com a especificação HTTP, é retornado quando um recurso é criado. Portanto, o retorno GET 201 será uma chamada de ativação (o código é usado incorretamente ou o GET cria o recurso). Portanto, nossa API de diretrizes proíbe esse uso. Além disso, os arquitetos fixaram conjuntos de códigos para cada método e agora os verificamos no modo estático no nível das anotações.
- Verificando métodos HTTP. Todo mundo sabe que o protocolo HTTP possui um conjunto de métodos padrão (GET, POST, PUT etc.) e também possibilita o uso de métodos personalizados. Nossa API de diretrizes descreve métodos permitidos que são permitidos, mas indesejáveis (OPTIONS), bem como completamente proibidos (só podem ser usados com a benção dos arquitetos). Proibido incluir o método HEAD padrão, bem como quaisquer métodos personalizados. Tudo isso também é fácil de verificar nas anotações dos contratos.
- Verificação de direitos de acesso. Esperamos que em 2019 a necessidade de suporte à autorização não exija explicações adicionais. Uma boa documentação deve incluir informações sobre quais funções a API suporta e quais métodos de API estão disponíveis para cada função. Além de documentar informações sobre o modelo, registrado no nível da anotação, permite que você faça coisas muito mais interessantes em dinâmica, no entanto, falaremos sobre isso no próximo artigo.
- Validação de nomeação. Alivia uma dor de cabeça ao usar abordagens diferentes para nomear entidades. Em geral, existem dois "campos" - apoiadores do CamelCase e snake_case.Camelcase - quando cada palavra começa com uma letra maiúscula e snake_case - quando as palavras são separadas por sublinhados e tudo é escrito em letras minúsculas. Em diferentes idiomas, é costume dar nomes de maneiras diferentes. Por exemplo, snake_case é aceito em Python e CamelCase é adotado em Go ou Java. Fizemos nossa própria escolha universal para todos os projetos e corrigimos as diretrizes da API. Portanto, através de anotações, verificamos os nomes dos recursos e parâmetros estaticamente;
- Validação de cabeçalhos personalizados. Este é outro exemplo de uma verificação de nomenclatura, mas está ligada especificamente às cabeças. Na Acronis, é habitual usar o formato no formato X-Custom-Header-Name (apesar de esse formato estar obsoleto). E controlamos sua conformidade no nível das anotações.
- Verifique o suporte HTTPS. Qualquer serviço moderno deve oferecer suporte a HTTPS, e alguns acreditam que trabalhar com HTTP atualmente é geralmente uma má notícia. Portanto, a anotação RAML ou Swagger deve ser indicada. que o microsserviço suporta HTTPS sem HTTP.
- Verifique a estrutura do URI. Em tempos pré-históricos, isto é, antes do lançamento da API Guideline, o URI da solicitação parecia diferente em diferentes serviços: em algum lugar / api / 2, em algum lugar / api / service_name / v2 e assim por diante. Agora, em nossas diretrizes, uma estrutura padrão de URI é definida para todas as nossas APIs. O manual descreve como eles devem parecer para não criar confusão.
- Verificando a compatibilidade de novas versões. Outro fator que qualquer autor de API deve ter em mente é a compatibilidade com versões anteriores. É importante verificar se o código criado com base na API antiga pode funcionar com a nova versão. Com base nessa alteração, pode ser dividido em duas categorias: quebrando a compatibilidade com versões anteriores e compatível. Todo mundo sabe que quebrar alterações é inaceitável e, se você quiser melhorar drasticamente alguma coisa, o desenvolvedor deve lançar uma nova versão da API. Mas todos podem cometer erros, então nosso outro objetivo no estágio de verificações estáticas é ignorar apenas as alterações compatíveis e xingar as incompatíveis. Supõe-se que a anotação, como o código, seja armazenada no repositório e, portanto, tenha todo o histórico de alterações. Portanto, podemos verificar nosso HTTP REST para compatibilidade com versões anteriores. Por exemplo, a adição de (método, parâmetro, código de resposta) compatibilidade não viola e a remoção pode causar perda de compatibilidade. E isso já pode ser verificado no nível da anotação.

Quando não há descrições

Quando houver descrições
Conclusões
A análise estática das anotações é necessária para verificar (não, não a qualidade do serviço), mas a qualidade da API. Esse estágio permite alinhar as interfaces do programa entre si, para que as pessoas trabalhem em um ambiente claro e compreensível, onde tudo seja razoavelmente previsível.
Obviamente, só é necessário lidar com esse formalismo em empresas grandes o suficiente, quando a verificação manual de todas as correspondências é muito longa, cara e não confiável. Uma pequena startup simplesmente não precisa dela. Pelo menos por enquanto. Mas se, no seu futuro, houver planos de se tornar um unicórnio, como o Akronis, as verificações estáticas e a API Guideline o ajudarão.