O que a HATEOAS oferece para a descoberta e desacoplamento, além da capacidade de alterar sua estrutura de URL mais ou menos livremente?

60

Ultimamente, tenho lido sobre a hipermídia como o mecanismo do estado do aplicativo (HATEOAS), a restrição reivindicada para tornar uma API da Web "verdadeiramente RESTful". Tudo se resume basicamente a incluir links com todas as respostas às possíveis transições que você pode fazer do estado atual.

Deixe-me ilustrar o que HATEOAS é baseado no meu entendimento - e por favor me corrija se eu perdi alguma coisa.

/
    GET: {
        "_links": {
            "child": [
                { "href": "http://myapi.com/articles", "title": "articles" }
            ]
        }
    }

/articles?contains=HATEOAS
    GET: {
        "_items": [
            { "uri": "http://myapi.com/articles/0", "title": "Why Should I Care About HATEOAS?" },
            { "uri": "http://myapi.com/articles/1", "title": "HATEOAS: Problem or Solution?" }
        ],
        "_links": {
            "self": { "href": "http://myapi.com/articles", "title": "articles" },
            "parent": { "href": "http://myapi.com/", "title": "home" }
        }
    }

    POST: {
        "title": "A New Article",
        "body": "Article body",
        "tags": [ "tag1", "tag2" ]
    }

/articles/0
    GET: {
        "title": "Why Should I Care About HATEOAS?",
        "body": "Blah blah blah"
        "tags": [ "REST", "HATEOAS" ],
        "_links": {
            "self": { "href": "http://myapi.com/articles/0", "title": "article" },
            "parent": { "href": "http://myapi.com/articles", "title": "articles" }
        }
    }

HATEOAS é alegado para fornecer dois benefícios principais:

  1. O serviço inteiro pode ser descoberto a partir do URI raiz, a documentação não é mais necessária.

  2. O cliente é dissociado do servidor, que agora pode alterar a estrutura do URI livremente. Isso elimina a necessidade de versões de APIs.

Mas, na minha opinião, um serviço é muito mais do que sua estrutura de URI. Para usá-lo efetivamente, você também precisa saber:

  • quais parâmetros de consulta você pode usar e seus possíveis valores
  • a estrutura do JSON / XML / qualquer documento que você precise enviar em suas solicitações POST / PATCH / etc
  • a estrutura da resposta enviada pelo servidor
  • os possíveis erros que podem ocorrer
  • ...

Com base no acima exposto, o HATEOAS resolve apenas uma pequena fração dos problemas de descoberta e acoplamento. Você ainda precisa documentar os quatro aspectos acima e os clientes ainda estarão strongmente acoplados ao servidor por causa deles. Para evitar a quebra de clientes, você ainda precisa da versão da sua API.

O único benefício que ele oferece é que você pode alterar sua estrutura de URL mais ou menos livremente (a propósito, o que aconteceu com o princípio " Cool URIs não mudam "?). Meu entendimento está correto?

    
por Botond Balázs 14.04.2014 / 08:12
fonte

4 respostas

45

Eu acho que seus instintos estão corretos; esses benefícios proclamados realmente não são tão bons assim, como para qualquer aplicativo da Web não trivial, os clientes precisarão se preocupar com a semântica do que estão fazendo, bem como com a sintaxe.

Mas isso não significa que você não deve fazer sua inscrição seguir os princípios da HATEOAS!

O que HATEOAS realmente significa? Isso significa estruturar seu aplicativo para que seja, em princípio, semelhante a um site e que todas as operações desejadas possam ser descobertas sem precisar fazer download de algum esquema complexo . (Esquemas WSDL sofisticados podem cobrir tudo, mas quando chegam, excedem a capacidade de praticamente todos os programadores entenderem, quanto mais escrever! Você pode ver HATEOAS como uma reação contra tal complexidade.)

HATEOAS não significa apenas links ricos. Significa usar os mecanismos de erro do padrão HTTP para indicar mais exatamente o que deu errado; você não precisa apenas responder com "waaah! não ”e pode, em vez disso, fornecer um documento descrevendo o que estava realmente errado e o que o cliente poderia fazer a respeito. Isso também significa dar suporte a itens como solicitações de OPÇÕES ( a maneira padrão de permitir que os clientes descubram quais métodos de HTTP eles podem usar) e negociação de tipo de conteúdo para que o formato da resposta possa ser adaptado a um formulário que os clientes possam manipular. Isso significa colocar texto explicativo (ou, mais provavelmente, links para ele) para que os clientes possam procurar como usar o sistema em casos não-triviais se não souberem; o texto explicativo pode ser legível por humanos ou pode ser legível por máquina (e pode ser tão complexo quanto você quiser). Finalmente, isso significa que clientes não sintetizam links (exceto para parâmetros de consulta); os clientes só usarão um link se você contasse para eles.

Você precisa pensar em ter o site visitado por um usuário (que pode ler JSON ou XML em vez de HTML, portanto, um pouco estranho) com uma excelente memória para links e um conhecimento enciclopédico do Padrões HTTP, mas sem o conhecimento do que fazer.

E, claro, você pode usar a negociação de tipo de conteúdo para servir um cliente HTML (5) / JS que permitirá que eles usem seu aplicativo, se é isso que o navegador está preparado para aceitar. Afinal, se a sua API RESTful é boa, isso deve ser “trivial” para implementar em cima dela?

    
por 14.04.2014 / 10:10
fonte
6

As coisas são, HATEOAS deve vir com um segundo pilar que define o que é uma API RESTful: tipo de mídia padronizado. O próprio Roy Fielding disse

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources".

Com um tipo de mídia padronizado que define a transição de forma explícita e o recurso de hipertexto para apontar um ao outro, você pode criar um gráfico de recursos que pode assumir qualquer forma sem quebrar nenhum cliente. Como o trabalho na web, realmente: você tem link entre documento e documento são escritos em HTML que definem como seguir esses links. <a href> é um GET, <form> é GET ou POST (e define o modelo de URL a ser usado no caso de GET), <link type="text/css"> é GET ... etc. É assim que navegadores podem navegar em páginas HTML estruturadas arbitrárias e Web.

Todo o ponto que você fez

  • what query parameters you can use and their possible values
  • the structure of the JSON/XML/whatever documents you need to send in your POST/PATCH/etc requests
  • the structure of the response sent by the server
  • the possible errors that might occur

São pontos que devem ser endereçados pela definição de seu tipo de mídia padronizado . Claro, isso é muito mais difícil, e não é algo que a maioria das pessoas pensa quando define uma API "REST". Você não pode simplesmente pegar suas entidades de negócios e inserir seus atributos em um documento JSON para ter uma API RESTful.

Claro, o que aconteceu é que o REST foi de alguma forma diluído para significar "use HTTP em vez de complicado SOAPy thingy". Apenas usar HTTP e HyperText não é suficiente para ser RESTful, isso é o que a maioria das pessoas erra.

Não que isso seja necessário a coisas ruins: REST sacrificar desempenho e facilidade de desenvolvimento em troca de manutenção e evolutividade a longo prazo. Foi feito para uma grande integração de aplicativos empresariais. Uma pequena API da Web com estrutura JSON codificada pode ser o que você precisa. Só não chame de REST, é uma API web ad-hoc, nada mais. E isso não significa que seja uma droga, significa apenas que não tenta seguir a restrição do REST.

Leitura adicional

Espero que essa ajuda esclareça um pouco:)

    
por 14.04.2014 / 21:13
fonte
2

Existem alguns formatos de hipermídia que se esforçam para fornecer respostas mais ricas, que incluem mais informações sobre que tipo de solicitações enviar, e não há nada que o impeça de enriquecer a resposta com ainda mais informações.

Veja um exemplo do documento Siren :

{
  "class": [ "order" ],
  "properties": { 
      "orderNumber": 42, 
      "itemCount": 3,
      "status": "pending"
  },
  "entities": [
    {
      "class": [ "info", "customer" ],
      "rel": [ "http://x.io/rels/customer" ], 
      "properties": { 
        "customerId": "pj123",
        "name": "Peter Joseph"
      },
      "links": [
        { "rel": [ "self" ], "href": "http://api.x.io/customers/pj123" }
      ]
    }
  ],
  "actions": [
    {
      "name": "add-item",
      "title": "Add Item",
      "method": "POST",
      "href": "http://api.x.io/orders/42/items",
      "type": "application/x-www-form-urlencoded",
      "fields": [
        { "name": "orderNumber", "type": "hidden", "value": "42" },
        { "name": "productCode", "type": "text" },
        { "name": "quantity", "type": "number" }
      ]
    }
  ],
  "links": [
    { "rel": [ "self" ], "href": "http://api.x.io/orders/42" },
    { "rel": [ "previous" ], "href": "http://api.x.io/orders/41" },
    { "rel": [ "next" ], "href": "http://api.x.io/orders/43" }
  ]
}

Como você pode ver, as informações sobre como chamar o actions relacionado são fornecidas na mensagem e, ao interpretar essas informações, o cliente fica mais resistente a alterações.

Torna-se particularmente poderoso se rel s são URIs que podem ser pesquisados, e não a partir de um vocabulário fixo.

    
por 15.08.2016 / 12:27
fonte
0

Onde você leu que "a documentação não é mais necessária" para os serviços HATEAOS? Como você diz, você ainda precisa documentar a semântica dos links. No entanto, com o HATEOAS você não precisa documentar e, portanto, manter para sempre a estrutura da maioria dos URIs.

O HATEOAS permite que um implementador de serviços modifique e dimensione a implementação de maneira significativa e eficiente sem alterar um pequeno conjunto de URIs do qual o cliente depende. É mais fácil manter um pequeno número de pontos de entrada inalterados do que um conjunto grande. Assim, reduzir o número de pontos de entrada públicos para o serviço e fornecer dinamicamente links para sub-recursos (HATEOAS) realmente suporta "URIs frios não mudam" melhor do que serviços não-HATEOAS.

    
por 14.04.2014 / 15:03
fonte