Quão útil / importante é REST HATEOAS (nível de maturidade 3)?


110

Estou me envolvendo em um projeto em que alguns membros da equipe sênior acreditam que uma API REST deve ser compatível com o HATEOAS e implementar todos os níveis de maturidade de Richardson ( http://martinfowler.com/articles/richardsonMaturityModel.html )!

A maioria das implementações do AFAIK REST não é compatível com o HATEOAS e deve haver um bom motivo para que mais pessoas não estejam fazendo isso. Posso pensar em razões como complexidade adicional, falta de estruturas (lado do servidor e do cliente), preocupação com o desempenho e ...

O que você acha? Você já teve alguma experiência com o HATEOAS em um projeto do mundo real?


Aqui está um bom artigo sobre o assunto: medium.com/@andreasreiser94/… Basicamente, a forma como "REST" é normalmente implementado, é RPC ...
masterxilo

Respostas:


213

Ninguém na comunidade REST diz que REST é fácil. HATEOAS é apenas um dos aspectos que adiciona dificuldade a uma arquitetura REST.

As pessoas não praticam HATEOAS por todos os motivos que você sugere: é difícil. Ele adiciona complexidade tanto ao lado do servidor quanto ao cliente (se você realmente quiser se beneficiar com isso).

NO ENTANTO, bilhões de pessoas experimentam os benefícios do REST hoje. Você sabe qual é a URL de "checkout" na Amazon? Eu não. Ainda assim, posso fazer checkout todos os dias. Esse URL mudou? Não sei, não me importo.

Você sabe se importa? Qualquer pessoa que escreveu uma tela raspou o cliente automatizado da Amazon. Alguém que provavelmente farejou meticulosamente o tráfego da web, leu páginas HTML etc. para descobrir quais links chamar, quando e com quais cargas úteis.

E assim que a Amazon mudou seus processos internos e estrutura de URL, esses clientes codificados falharam - porque os links quebraram.

No entanto, os surfistas casuais da web conseguiam fazer compras o dia todo sem nenhum problema.

Isso é REST em ação, é apenas aumentado pelo ser humano que é capaz de interpretar e intuir a interface baseada em texto, reconhecer um pequeno gráfico com um carrinho de compras e descobrir o que isso realmente significa.

A maioria das pessoas que escrevem software não faz isso. A maioria das pessoas que escrevem clientes automatizados não se importa. A maioria das pessoas acha mais fácil consertar seus clientes quando eles quebram do que projetar o aplicativo para não quebrar em primeiro lugar. A maioria das pessoas simplesmente não tem clientes suficientes onde é importante.

Se você está escrevendo uma API interna para se comunicar entre dois sistemas com suporte técnico especializado e TI em ambos os lados do tráfego, que são capazes de comunicar as mudanças de forma rápida, confiável e com um cronograma de mudanças, então o REST não compra nada. Você não precisa disso, seu aplicativo não é grande o suficiente e não dura o suficiente para ser importante.

Grandes sites com grandes bases de usuários têm esse problema. Eles não podem simplesmente pedir às pessoas que alterem seu código de cliente por capricho ao interagir com seus sistemas. O cronograma de desenvolvimento de servidores não é o mesmo que o cronograma de desenvolvimento do cliente. Mudanças abruptas na API são simplesmente inaceitáveis ​​para todos os envolvidos, uma vez que interrompe o tráfego e as operações em ambos os lados.

Portanto, uma operação como essa provavelmente se beneficiaria com o HATEOAS, pois é mais fácil de criar versões, mais fácil para clientes mais antigos migrarem, mais fácil ser compatível com versões anteriores do que não.

Um cliente que delega grande parte de seu fluxo de trabalho para o servidor e age de acordo com os resultados é muito mais robusto para alterações no servidor do que um cliente que não o faz.

Mas a maioria das pessoas não precisa dessa flexibilidade. Eles estão escrevendo código de servidor para 2 ou 3 departamentos, é tudo para uso interno. Se ele quebrar, eles consertam e incluem isso em suas operações normais.

Flexibilidade, seja de REST ou qualquer outra coisa, gera complexidade. Se você quer algo simples e rápido, você não o torna flexível, você "apenas faz" e pronto. Conforme você adiciona abstrações e desreferenciamento aos sistemas, as coisas ficam mais difíceis, mais clichê, mais código para testar.

Muito do REST falha no ponto de bala "você não vai precisar". Até, claro, você fazer.

Se precisar, use-o e use-o como está definido. REST não está empurrando coisas para frente e para trás no HTTP. Nunca foi, é um nível muito mais alto do que isso.

Mas quando você precisa de REST e usa REST, o HATEOAS é uma necessidade. É parte do pacote e a chave para o que o faz funcionar.


11
Acho que você deveria ter pelo menos mais mil curtidas para esta resposta. Honestamente, eu tenho que imaginar: Qual a importância de ser 'real' A questão REST surge um pouco. Inferno, eu estava pesquisando no Google exatamente por esse motivo de munição para usar em uma próxima reunião quando encontrei este tópico.
nograde

2
graças a deus (ou código), alguém está falando sobre as desvantagens do HATEOAS também!
IlliakaillI

6
Existe alguma outra vantagem além da capacidade de alterar URLs facilmente? Você não pode simplesmente adicionar novas opções porque, ao contrário dos humanos, o programa não pode funcionar com algo novo. Além disso, você apenas deixou de construir URLs conhecidas para saber o nome das ações.
Jimmy T.

Se o consumidor da API não souber de nada, ele só poderá delegar ações do usuário 1: 1
Jimmy T.

2
Em relação à mudança de URLs, não se esqueça que seu cliente pode usar cache e, portanto, você deve manter o comportamento do servidor para lidar com a URL anterior também (ou apenas fazer um redirecionamento). Como qualquer estratégia para desenvolver APIs, você deve manter seu antigo comportamento funcionando. HATEOAS não ajuda muito nisso.
Bruno Costa

21

Sim, tenho alguma experiência com hipermídia em APIs. Aqui estão alguns dos benefícios:

  1. API explorável: pode parecer trivial, mas não subestime o poder de uma API explorável. A capacidade de navegar pelos dados torna muito mais fácil para os desenvolvedores do cliente construir um modelo mental da API e suas estruturas de dados.

  2. Documentação embutida: O uso de URLs como relações de link pode apontar os desenvolvedores de cliente para a documentação.

  3. Lógica de cliente simples: um cliente que simplesmente segue URLs em vez de construí-los sozinho, deve ser mais fácil de implementar e manter.

  4. O servidor assume a propriedade das estruturas de URL: O uso de hipermídia remove o conhecimento codificado do cliente das estruturas de URL usadas pelo servidor.

  5. Descarregando conteúdo para outros serviços: A hipermídia é necessária ao descarregar conteúdo para outros servidores (um CDN, por exemplo).

  6. Controle de versão com links: a hipermídia ajuda no controle de versão de APIs.

  7. Várias implementações do mesmo serviço / API: Hipermídia é uma necessidade quando existem várias implementações do mesmo serviço / API. Um serviço pode ser, por exemplo, uma API de blog com recursos para adicionar postagens e comentários. Se o serviço for especificado em termos de relações de link em vez de URLs codificados, o mesmo serviço pode ser instanciado várias vezes em URLs diferentes, hospedado por empresas diferentes, mas ainda acessível por meio do mesmo conjunto bem definido de links por um único cliente.

Você pode encontrar uma explicação detalhada desses pontos aqui: http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html

(há uma pergunta semelhante aqui: /software/149124/what-is-the-benefit-of-hypermedia-hateoas onde dei a mesma explicação)


Várias implementações do mesmo serviço: você pode elaborar? Não vejo como isso ajuda.
Abbadon,

Tentei explicar no texto. Ajuda?
Jørn Wildt

11

O nível de maturidade 3 de Richardson é valioso e deve ser adotado. Jørn Wildt já resumiu algumas vantagens e uma outra resposta, de Wilt, complementa muito bem.

No entanto, o nível de maturidade 3 de Richardson não é o mesmo que o HATEOAS de Fielding. O nível de maturidade 3 de Richardson é apenas sobre design de API. O HATEOAS de Fielding também se refere ao design de API, mas também prescreve que o software cliente não deve presumir que um recurso tem uma estrutura específica além da estrutura definida pelo tipo de mídia. Isso requer um cliente muito genérico, como um navegador da web, que não tem conhecimento sobre sites específicos. Como Roy Fielding cunhou o termo REST e definiu HATEOAS como um requisito para conformidade com REST, a questão é: queremos adotar HATEOAS e se não, ainda podemos chamar nossa API de RESTful ou não? Eu acho que podemos. Deixe-me explicar.

Suponha que tenhamos alcançado o HATEOAS. O lado do cliente do aplicativo agora é muito genérico, mas provavelmente a experiência do usuário é ruim, porque sem nenhum conhecimento da semântica dos recursos, a apresentação dos recursos não pode ser adaptada para refletir essa semântica. Se o recurso 'carro' e o recurso 'casa' tiverem o mesmo tipo de mídia (por exemplo, aplicativo / json), eles serão apresentados ao usuário da mesma forma, por exemplo, como uma tabela de propriedades (pares de nome / valor).

Mas tudo bem, nossa API é realmente RESTful.

Agora, suponha que construamos um segundo aplicativo cliente sobre esta API. Este segundo cliente viola as ideias do HATEOAS e possui informações embutidas em código sobre os recursos. Ele exibe um carro e uma casa de maneiras diferentes.

A API ainda pode ser chamada de RESTful? Acho que sim. Não é culpa da API que um de seus clientes tenha violado o HATEOAS.

Aconselho a construir APIs RESTful, ou seja, APIs para as quais um cliente genérico pode ser implementado em teoria , mas na maioria dos casos, você precisa de algumas informações embutidas em código sobre os recursos em seu cliente para atender aos requisitos de usabilidade. Ainda assim, tente codificar o menos possível, para reduzir as dependências entre cliente e servidor.

Incluí uma seção sobre HATEOAS em meu padrão de implementação REST chamado JAREST .


8

Estamos construindo uma API REST de nível 3 em que nossa resposta está em HAL-Json. O HATEOAS é ótimo para front-end e back-end, mas vem com desafios. Fizemos algumas personalizações / adições para também gerenciar ACL dentro da resposta HAL-Json (que não quebra o padrão HAL-Json).

As maiores vantagens do HATEOAS que vejo é que não precisamos escrever / adivinhar nenhuma urls em nosso aplicativo front-end. Tudo o que você precisa é de um ponto de entrada ( https://hostname) e, a partir daí, você pode simplesmente navegar pelos recursos usando os links ou links de modelo fornecidos dentro da resposta. Assim, o controle de versão pode ser feito facilmente, renomeando / substituindo urls, estendendo recursos com relações adicionais sem quebrar o código de front-end.

O armazenamento em cache de recursos no front-end é muito fácil usando links próprios. Também enviamos recursos para clientes por meio de uma conexão de soquete, já que eles também são renderizados em HAL, poderíamos facilmente adicioná-los ao cache da mesma maneira.

Outra vantagem de usar HAL-Json é que fica claro como o modelo de resposta deve se parecer, já que há um padrão documentado que deve ser seguido.

Um dos nossos personalizações é que nós adicionamos um objetos ações dentro do objeto auto-link que expõe para o front-end que ações ou operações CRUD o usuário autenticado tem permissão para executar no respectivo recurso ( create:POST, read:GET, update:PUT, edit:PATCH, delete:DELETE). Assim, nossa ACL de front-end é totalmente ditada por nossa resposta da API REST, transferindo essa responsabilidade totalmente para o modelo de back-end.

Então, para dar um exemplo rápido, você poderia ter um objeto de postagem em HAL-Json que se parece com isto:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "update": "PUT",
                "delete": "DELETE"
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "john.doe@example.com",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET"
                    }
                }
            }
        }
    },
    "subject": "Post subject",
    "body": "Post message body"
}

Agora tudo o que temos que fazer no front end é construir um AclServicecom um isAllowedmétodo que verifica se a ação que queremos realizar está no objeto actions.

Atualmente no front-end parece tão simples como: post.isAllowed('delete');

Acho REST nível 3 ótimo, mas pode levar a algumas dores de cabeça. Você precisará ter um grande conhecimento de REST e se quiser trabalhar com REST de nível 3, sugiro seguir estritamente o conceito de REST, caso contrário, você se perderá facilmente ao implementá-lo.

Em nosso caso, temos a vantagem de estar construindo front-end e back-end, mas em princípio NÃO deve fazer diferença. Mas uma armadilha comum que vi em nossa equipe é que alguns desenvolvedores tentam resolver problemas de front-end (arquitetura) mudando seu modelo de back-end para que "se adapte" às ​​necessidades de front-end.


1
Muito boa resposta. Acho que esse exemplo prático era o que o questionador original estava procurando.
www.admiraalit.nl

2

Usei HATEOAS em alguns projetos reais, mas com uma interpretação diferente de Richardson. Se é isso que seus chefes querem, acho que você deveria simplesmente fazer. Entendo que HATEOAS significa que seus recursos devem incluir um doctype HTML, hiperlinks para recursos relacionados e formulários HTML para expor a funcionalidade de verbos diferentes de GET. (Isso é quando o tipo Aceitar é text / html - outros tipos de conteúdo não exigem esses extras.) Não sei de onde veio a crença de que todos os recursos REST em todo o seu aplicativo devem ser colados. Um aplicativo de rede deve conter vários recursos que podem ou não estar diretamente relacionados. Ou por que se acredita que XML, JSON e outros tipos precisam seguir isso. (HATEOAS é específico para HTML.)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.