BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Programando com profiles semânticos: na terra das strings mágicas, o profile é o rei

Programando com profiles semânticos: na terra das strings mágicas, o profile é o rei

Favoritos

Em 2012, vários meses foram gastos no desenvolvimento de uma biblioteca para aplicações clientes de uma plataforma SOA "RESTful" proprietária, juntamente com um mecanismo de descoberta de serviços e suas respectivas APIs cliente, baseado na API Discovery Service do Google. Durante a execução do projeto havia uma pequena questão em um story card que seria ignorada até que a biblioteca para os clientes "RESTful" estivesse finalizada: "Implementar HATEOAS" (Hypermedia as the engine of application state). Entretanto, muitos problemas poderiam ter sido evitados com a priorização daquele story card.

Fundamentos

Quando finalmente aquele story card foi iniciado, ocorreu um processo mais profundo de entendimento sobre APIs, que influenciou a modelagem e o desenvolvimento de um framework de mensagens Hipermídia, além de um mecanismo de descoberta de serviços para uma plataforma proprietária. Dessa forma, é possível enumerar alguns fundamentos que se aplicam à APIs Hipermídia e também à APIs baseadas em HTTP/REST.

  1. Uma API Hipermídia deve ser projetada e entendida como uma máquina de estados, com semântica clara e bem definida para os dados e transições.
  2. A incorporação da descrição da API em rotas, controladores, modelos e comentários de código torna quase impossível visualizar e compreender os recursos e a máquina de estados.
  3. Cada recurso deve possuir uma declaração explícita em um documento de descrição de API em um formato legível por máquina (machine-readable), semelhante ao Blueprint API, Swagger ou outras, que em um só lugar descreva todos os aspectos do recurso, incluindo a sua semântica, máquina de estados, recursos relacionados e até mesmo detalhes de implementação específicos de protocolo.
  4. O desenvolvimento de mecanismos para utilizar o documento de descrição da API para gerar respostas. Deve-se abstrair totalmente a implementação do modelo de dados local por meio da descrição dos recursos da API. Para mais informações sobre a conversão de modelos de dados locais e definição de recursos da API, consulte o Padrão Representor.
  5. A disponibilização de documentos de descrição de API é um anti-padrão que resulta em alto acoplamento e fragilidade, pois expõe detalhes de implementação que devem ser internos. Estes documentos de descrição devem ser utilizados para modelagem, documentação e geração de respostas pelo servidor. Sendo assim, não devem ser usados por aplicações clientes.
  6. Uma máquina deve ser capaz de interagir com uma API Hipermídia bem definida, de forma a permitir uma interação no formato follow the nose, semelhante a interação executada por um ser humano.
  7. Todos os detalhes necessários para a interação entre uma API com suporte Hipermídia e um consumidor, humano ou máquina, devem ser compartilhados em tempo de execução, a fim de garantir o baixo acoplamento além de facilitar a evolução dos sistemas, como descrito nos princípios arquiteturais REST.

Durante a conferência QCon 2013 em Londres, Mike Amundsen fez sua primeira apresentação sobre Application Level-Profile Semantics (ALPS) e profiles. Um slide em particular, que cita a tese de Roy Fielding, chamou a atenção: "REST proporciona [a troca de informações entre clientes e servidores]" através de um entendimento compartilhado dos tipos de dados por meio de metadados…"- Roy T. Fielding.

Esta citação no contexto de profiles semânticos fortalece os fundamentos enumerados anteriormente. Profiles, em particular o ALPS, agrupam os recursos da API com a descrição da máquina de estados, fato que resulta no entendimento compartilhado entre seres humanos e máquinas, e na definição da semântica das mensagens em tempo de execução.

Ao final da conferência, iniciou-se o desenvolvimento de um framework Himermídia para Rails[1], que utiliza uma linguagem baseada em ALPS para a descrição interna da API e para a descrição de dados e transições. Com isso, foi possível perceber vários benefícios e limitações do uso de profiles, bem como vários preconceitos sobre o real significado dos recursos e como as APIs deveriam disponibilizar os dados para os clientes.

Uma breve apresentação do ALPS

Um aspecto interessante da utilização do ALPS como profile de dados é o desacoplamento total entre a mensagem e a sua semântica, independente do formato. Outros profiles e abordagens exigem que a descrição semântica seja incorporada na mensagem, por exemplo: Microdata em HTML ou contextos em JSON-LD. ALPS transcende os media types por meio de simples regras de mapeamento de elementos em uma mensagem com seus descritores semânticos, dado um media type específico.

http://example.com/alps/works

De forma muito simples, o ALPS descreve a semântica através da especificação de um id associado a um descritor, juntamente com um tipo (atributo type). O atributo type pode ser "semântico", correspondente à descrição de um elemento de dado, "seguro (safe)", "idempotente" ou "não seguro (unsafe)", de acordo com a natureza da transição. Descritores de tipos de transição também permitem a definição de tipos de relacionamentos personalizados. O exemplo a seguir apresenta um profile ALPS localizado em http://example.com/alps/works:

<alps version="1.0">
  <descriptor id="content" type="semantic">
    <doc>O conteúdo de um trabalho</doc>
  </descriptor>
  <descriptor id="publish" type="idempotent">
    <doc>Liberar um trabalho para distribuição</doc>
  </descriptor>
</alps>

Para uma mensagem application/json, a resposta correspondente é:

GET /works/1 HTTP/1.1
Host: example.io
Links: profile="http://example.com/alps/works”
Content-Type: application/json

{
  "content" : "The ships hung in the sky in much the same way that bricks don't."
}

Para uma mensagem application/vnd.siren+json, a resposta correspondente é:

GET /works/1 HTTP/1.1
Host: example.io
Links: profile="http://example.com/alps/works”
Content-Type: application/vnd.siren+json

{
  "properties" {
    "content" : "The ships hung in the sky in much the same way that bricks don't."
  },
  "actions" : {
    "name" : "publish",
    "method" : "PUT",
    "href" : "..."
  }
}

Devido o Siren ser um media type com suporte hipermídia, o descritor da transição (<descriptor . . ./>) pode mapear diretamente a mensagem (por exemplo, o elemento action do Siren). Por outro lado, um JSONplano não possui o conceito de links ou formulários hipermídia, sendo assim, o descritor "publish" não pode ser representado em JSON. Isto enfatiza a simplicidade e o poder de reúso dos profiles ALPS. A semântica da API é definida de forma independente dos media types de representação, fato que permite aos clientes mapearem os detalhes semânticos de acordo com as representações recebidas.

Profiles e APIs

Profiles permitem criar uma linguagem ubíqua para descrever os recursos de APIs de forma adequada para seres humanos e também para máquinas. Por meio de um vocabulário reusável, organizado e confiável, os profiles superam as limitações das "strings mágicas" amarradas ao domínio, pois os detalhes geralmente estão incorporados à documentação da API.

Diferente de Resource Description Framework (RDF), Web Ontology Language (OWL) e muitos outros modelos de dados, vocabulários e definições de profiles, ALPS é muito simples. Basta definir a semântica dos dados e transições em um formato intuitivo com descrições legíveis aos seres humanos. Entretanto, existem outras etapas que devem ser realizadas para que a semântica não continue sendo apenas "strings mágicas" do profile.

ALPS estabelece o registro de persistência das definições para um reúso consistente. O princípio fundamental é disponibilizar o profile de forma permanente para permitir que seja referenciado. Uma vez que um autor não altere o significado semântico dos descritores previamente disponibilizados (fato que quebraria o contrato), o profile pode ser utilizado outras vezes como fonte confiável de informação semântica.

Estes registros são chamados de dicionários, uma vez que: profiles definitivamente definem vocabulários. A medida que reutilizam outros vocabulários, os profiles tornam-se ubíquos. Um exemplo de reutilização de outros vocabulários é o conjunto de profiles ALPS desenvolvidos a partir das definições do Schema.org. Uma vez que existe um ecossistema de profiles, como previsto no projeto ALPS, existem inúmeras possibilidades de uso do ALPS aplicáveis ao design, implementação e interação de APIs.

Profiles e a modelagem de APIs

Através de um exemplo simplificado de modelagem de APIs com profiles, será desenvolvida uma API para interagir com uma porta. O desenvolvimento inicia-se com um brainstorm sobre a semântica e a máquina de estados dos dados, além das transições (affordance) dos recursos que representam uma porta. O resultado pode ser visto a seguir:

Com uma ideia aproximada da semântica do novo recurso, a próxima questão é verificar a existência de algum conceito relacionado que pode ser reutilizado. Uma breve pesquisa encontra dois profiles registrados em http://example.com/alps:

http://example.com/alps/portals

<alps version="1.0">
  <descriptor id="material" type="semantic">
    <doc>Material de fabricação da porta

http://example.com/alps/fasteners
<alps version="1.0">
  <descriptor id="knob" type="semantic"/>
  <descriptor id="latch" type="semantic"/>
</alps>

Revendo estes dois documentos ALPS pode-se notar:

  1. O descritor semântico do material da porta já está definido.
  2. Os descritores "open" (aberto) e "close" (fechado) definem as transições desejadas.
  3. Não existe um descritor para o puxador. Entretanto, existe uma definição similar: "knob" (maçaneta).

Com a adoção do descritor "knob", o recurso é definido com base em uma semântica já existente, sem a necessidade de criar um novo elemento semântico exclusivo para um cenário. Pode-se argumentar que desenvolvedores de aplicações clientes desejarão utilizar na interface gráfica o seu próprio identificador semântico: "puxador". Entretanto, isso é uma preocupação de apresentação, e como discutido mais adiante, as APIs devem utilizar a semântica mais abrangente possível, e deixar as variações de apresentação completamente separadas da semântica da API propriamente dita. Sendo assim, utilizando o documento ALPS como referência, pode-se definir o profile de uma porta como:

http://example.com/alps/doors

<alps version="1.0">
  <descriptor id="door" type="semantic">
    <descriptor href="http://example.com/alps/portals"/>
    <descriptor href="http://example.com/alps/fasteners#knob"/>
  </descriptor>
</alps>

Nota-se que a transição "self" no diagrama de estado de máquina não está definida explicitamente como um descritor no documento ALPS, pois esta transição representa um tipo de relacionamento, além de ser um link devidamente registrado no IANA. Entretanto, os descritores de "aberto" e "fechado" definem links personalizados de tipos de relacionamentos, associados com a máquina de estados das transições. Uma vez que se trata de um exemplo simplificado, pode-se adotar uma abordagem não estruturada para a composição de profiles, fato que enfatiza alguns aspectos chave do uso de ALPS como ferramenta de modelagem de APIs.

Muitos destes aspectos baseiam-se nos conceitos propostos em Resource Blueprint, que é um exemplo de uma nova geração de linguagens de descrição de APIs consciente de um profile. Esta linguagem baseia-se na ideia da definição e reutilização da semântica dos recursos, além do uso de profiles ALPS como parte integrante de ferramentas para modelagem de APIs. A vantagem de utilizar esta forma de modelagem pode ser percebida na simplicidade da comunicação com clientes capazes de interpretar ALPS em tempo de execução, por exemplo:

GET /doors/1 HTTP/1.1
Host: example.com
Links: profile="http://example.com/alps/doors", type="http://example.com/alps/doors#door"
Content-Type: application/vnd.siren+json

Com o mínimo de informações do exemplo anterior, um servidor disponibiliza informações completas a respeito de seu funcionamento, em um formato adequado para seres humanos e máquinas. Ainda mais importante, os detalhes internos de implementação não são disponibilizados, como é o caso de diversas abordagens de descrição de APIs.

Profiles na forma de restrições

A arquitetura está relacionada com um conjunto de restrições autoimpostas que resultam em propriedades favoráveis para um dado sistema. Sendo assim, a utilização de profiles na modelagem de APIs impõe restrições que resultam em simplicidade, entendimento e reusabilidade dos recursos.

Por serem semanticamente proficientes, os seres humanos não se dão conta de certas coisas durante o processo de modelagem de APIs. Durante a modelagem, são introduzidos elementos que funcionam bem para seres humanos, mas que não são adequados para as máquinas. Quando isto acontece, são introduzidas complexidades despercebidas.

Por exemplo, pode-se escrever uma documentação e, despercebidamente, referenciar uma lista de opções que pode ser acessada de forma muito natural (e frágil) pelos seres humanos. Entretanto, para um sistema que deve reagir a mudanças, em tempo de execução, esta prerrogativa humana não se aplica.

Profiles mantém as coisas como elas são de verdade. Sendo assim, a restrição de que APIs possam ser interpretadas por máquinas (assumindo que os clientes sejam capazes de compreender a semântica utilizada) implica em uma modelagem muito mais adequada e simples. A experiência mostra que a utilização de ALPS resulta no desenvolvimento de APIs mais simples e ricas semanticamente.

Governança semântica entre times distribuídos

Dependendo do tamanho da organização e do nível de consistência desejado entre as APIs, profiles podem ser uma ferramenta muito útil. O uso de ferramentas para validar a modelagem das APIs em toda a organização, no lugar de utilizar um conjunto de regras, permite aos projetistas receber um feedback semântico. Além disso, alertar os projetistas quanto ao uso correto da semântica, juntamente com a utilização dos padrões definidos pela organização, resultam no aumento da consistência e um menor consumo de tempo.

É ainda mais vantajoso quando a descrição de novos elementos de dados semânticos é amplamente discutida. É muito útil para os arquitetos identificar quando novos dados semânticos estão sendo introduzidos no ecossistema. Esta é uma boa maneira para satisfazer as necessidades de front-end de um único sistema, frente à melhor semântica para o atual domínio suportado pelas APIs existentes.

Feedback da modelagem em tempo real

Semelhante ao auxílio dado à governança semântica, profiles podem capacitar a próxima geração de IDEs de modelagem de APIs ao adicionar "um senso de inteligência". Através de um pequeno contexto lógico, IDEs podem recomendar descritores de dados e links de relacionamentos adequados, além de incluir dados estatísticos de uso de semântica semelhante. A multidão nem sempre tem a razão, mas seria útil saber, por exemplo, que 90% das APIs usam o termo "nomeDeRegistro" (givenName) em vez de "primeiroNome" (firstName).

Conversão por tipo

Uma das melhores lições que se pode ter a respeito da modelagem de APIs com profiles é parar de utilizar a conversão "por tipo" do modelo de dados do domínio diretamente aos clientes. Uma maneira obscura de implementar "REST" é incorporar o modelo de dados em URIs e convertê-lo diretamente para o modelo orientado a objetos (OOP em inglês) para o cliente. Esta prática distorce o fato de que recursos HTTP são apenas dados semânticos e controles.

Modelar APIs considerando o uso de semântica e profiles resulta no abandono da conversão por tipo. Esta forma de modelar cria novas possibilidades para especificar recursos em tempo de execução, além de fornecer uma compreensão semântica para os seres humanos e máquinas. A semântica é definida em termos abstratos, sem depender de estruturas concretas ou coleções de propriedades. Esta ideia pode parecer estranha, mas na verdade é uma forma poderosa de modelar os dados disponibilizados por APIs.

Abstração/generalização de recursos

Durante o desenvolvimento do framework mencionado anteriormente, achou-se que o ALPS poderia viabilizar a renderização da estrutura dos dados juntamente com os detalhes das transições de estado na mensagem. Entretanto, utilizar ALPS apenas como guia para a renderização de mensagens possui limitações, uma vez que profiles não disponibilizam detalhes importantes de implementação, como URIs ou métodos do protocolo etc.

Para solucionar este problema, o ALPS foi estendido para um novo formato de descrição de APIs, capaz de contemplar estes detalhes de implementação, além de mapear as propriedades do modelo de dados à mensagens através de referências para profiles ALPS. Umas das principais desvantagens em utilizar profiles para representar estruturas torna-se dolorosamente óbvia: se um autor adicionar novos descritores a um profile já existente, as implementações podem tentar apresentar os novos atributos imediatamente, mesmo que o modelo de domínio não contenha estas informações. A conclusão é, em vez de delegar aos profiles os detalhes de apresentação, as linguagens de descrição de APIs deveriam direcionar a apresentação (através de ferramentas personalizadas) enquanto incorporam as informações de profile nas respostas.

Apoio na descoberta

De forma semelhante à algumas das ideias sobre descoberta de recursos, como por exemplo JSON Home, que simplesmente disponibilizam uma lista de profiles disponíveis, APIs podem facilmente disponibilizar um dicionário que descreve os recursos. A disponibilização destes profiles proporciona uma miríade de oportunidades para a configuração automática dos clientes.

Criação dinâmica de recursos

Serviços descritos por profiles podem delegar aos usuários a definição prévia de subconjuntos de dados. Um dos desafios de algumas grandes indústrias que ainda utilizam APIs baseadas em SOAP são os enormes esquemas de dados. Estas indústrias almejam começar a usar aplicações clientes móveis, e estão lutando para encontrar uma forma de refinar grandes quantidades de informações e disponibilizá-las em APIs baseadas em JSON. Utilizar profiles para definir subconjuntos de informações é uma alternativa para solucionar este problema.

Outra alternativa é a composição de serviços para geração dinâmica de novos recursos. Através da composição de dados e informações, e da adição dinâmica de metadados de profiles que contemplam a semântica dos novos recursos, clientes conscientes de profile podem se adaptar e utilizar os novos recursos em seus fluxos de trabalho.

Profiles e clientes

Serviços capazes de apresentar informações de profile através de mensagens oferecem uma variedade de novas possibilidades, tanto para clientes frond-end quanto para clientes back-end (servidores que compõem outras APIs).

Apresentação e modelagem semântica

Uma das ideias do ALPS é o compartilhamento de conceitos que PODEM estar presentes nas mensagens. Sendo assim, desenvolvedores de aplicações clientes conscientes de profiles podem abstrair a implementação da camada de apresentação. Isto poderia ser feito através da transformação da resposta da API em um modelo mais conveniente, além da utilização de tratadores capazes de lidar com a ausência de determinadas informações. Esta técnica é capaz de prevenir diversas fragilidades associadas ao acoplamento das aplicações clientes e aos detalhes de implementação da API, e permitir a evolução dos clientes hipermídia de forma independente.

Clientes móveis dinâmicos e a localização

É muito interessante a possibilidade de desenvolver frameworks leves para o desenvolvimento de aplicações clientes móveis, que permitam a interação com APIs de forma customizável. É possível criar profiles para melhor representar as mensagens em um cliente móvel (controles, botões, estilos, etc). Clientes móveis podem então obter as informações de APIs, e com base no profile, apresentar dinamicamente formulários, listas, etc.

De forma semelhante, bibliotecas de localização podem ser simplificadas com o uso de profiles. Alguns formatos de dados utilizam informações de localização legíveis somente aos seres humanos. Esta abordagem exige que a implementação da localização seja realizada internamente. Entretanto, retornar a semântica de um conjunto de informações através de um profile permite aos clientes que utilizam bibliotecas de localização, reconhecer a semântica utilizada e realizar, de forma direta, o mapeamento das informações para seus respectivos elementos internos.

Clientes Inteligentes/consumidores automatizados

Por fim, sem o uso de profiles é virtualmente impossível que futuros clientes ou máquinas automatizadas que agem como clientes, executem ações de forma autônoma. Para clientes com conhecimento semântico, profile é o caminho para o entendimento e utilização de mensagens para futuras gerações de consumidores automatizados de APIs. Quanto antes os profiles se tornarem ubíquos no ambiente de APIs, mais cedo estas possibilidades se expandirão.

Conclusão

Profiles realmente auxiliam a pensar melhor sobre APIs. Sem profiles, o ambiente de APIs está cegamente condicionado ao uso de mensagens formadas por strings mágicas, passando a falsa ideia de tratar-se de informações semanticamente confiáveis. Espera-se que, em um futuro não tão distante, ferramentas de design de profile ajudarão os programadores a "pensar melhor" e construir clientes e servidores capazes de trabalhar melhor em muitos níveis - suportado por um ecossistema de profiles.

"Eu acredito que a melhor maneira de obter melhores programas é ensiná-los a pensar melhor." - Leslie Lamport

Sobre o autor

Mark W. Foster começou como cientista pesquisador em bio-sensing optoeletrônicas, transitava pelo mundo de sistemas e administração de banco de dados, infraestrutura de TI e computação empresarial, tornando-se um desenvolvedor e arquiteto de APIs. Trabalha atualmente na Apiary e participa de diversos projetos pioneiros de ferramentas para APIs Hipermídia. É também coautor da especificação ALPS. Você pode acompanhar Mark no Twitter em @fosrias.

Referências

1. Projeto Crichton. Inicialmente open-source, atualmente desenvolvido internamente. Futuras atualizações podem ser disponibilizadas nesta fonte.

Este artigo InfoQ é parte da série "Descrição, descoberta e profiles: O próximo nível em Web APIs". Para receber notificações sobre novos artigos desta série clique aqui.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT