Por que um pequeno vocabulário fixo é visto como uma vantagem para os serviços RESTful?

13

Portanto, um serviço RESTful possui um conjunto fixo de verbos em seu vocabulário. Um serviço da Web RESTful os utiliza dos métodos HTTP. Existem algumas supostas vantagens em definir um vocabulário fixo, mas eu realmente não entendo o ponto. Talvez alguém possa explicar isso.

Por que um vocabulário fixo, conforme descrito pelo REST, é melhor do que definir dinamicamente um vocabulário para cada estado? Por exemplo, a programação orientada a objetos é um paradigma popular. O RPC é descrito para definir interfaces fixas, mas não sei por que as pessoas assumem que o RPC é limitado por essas restrições. Poderíamos especificar dinamicamente a interface, assim como um serviço RESTful descreve dinamicamente sua estrutura de conteúdo.

O REST deve ser vantajoso, pois pode crescer sem estender o vocabulário. Os serviços RESTful crescem dinamicamente adicionando mais recursos. O que há de errado em estender um serviço especificando dinamicamente um vocabulário por objeto? Por que não usamos apenas os métodos definidos em nossos objetos como vocabulário e nossos serviços descrevem ao cliente o que são esses métodos e se eles têm ou não efeitos colaterais?

Essencialmente, sinto que a descrição de uma estrutura de recursos no servidor é equivalente à definição de um vocabulário, mas somos forçados a usar o vocabulário limitado no qual interagir com esses recursos.

Um vocabulário fixo realmente dissocia as preocupações do cliente das preocupações do servidor? Eu certamente tenho que me preocupar com alguma configuração do servidor, normalmente esse é o local dos recursos nos serviços RESTful. Reclamar pelo uso de um vocabulário dinâmico parece injusto, porque precisamos raciocinar dinamicamente como entender essa configuração de alguma maneira. Um serviço RESTful descreve as transições que você pode fazer identificando a estrutura do objeto por meio da hipermídia.

Apenas não entendo o que torna um vocabulário fixo melhor do que qualquer vocabulário dinâmico autoexplicativo, o que poderia facilmente funcionar muito bem em um serviço semelhante a RPC. Esse é apenas um mau raciocínio para o vocabulário limitador do protocolo HTTP?

Reflexão

Apenas para esclarecer meus pensamentos um pouco melhor do que eu fiz. Suponha que você esteja criando uma API de uso geral, talvez nem mesmo voltada para a web. Você ficaria feliz se alguém dissesse que você só pode usar esses nomes de métodos em seus objetos? O REST não se restringe ao HTTP, mas considere a situação em que todas as APIs que você escreve, voltadas para a Web ou simplesmente consistem em objetos que contêm os métodos GET POST PUT e DELETE. Portanto, esse método object.foo que você deseja definir não é possível. Você precisa definir um novo objeto chamado foo e chamar seu método GET. É basicamente assim que o REST funciona, e me deixa um pouco desconfortável pensar nisso. Você não tem um entendimento genérico melhor do que o foo faz, apenas foi forçado a criar um novo objeto para o que é essencialmente um método em um objeto pai. Além disso, sua API não é menos complexa, você acabou de ocultar a complexidade da interface criando mais objetos. Os serviços web RESTful nos forçam a adotar uma interface que pode ou não ser suficiente no contexto da API que estamos expondo. Talvez haja um bom motivo para fazer isso com APIs voltadas para a Web, mas um bom motivo para não adotar interfaces padrão para todos os objetos em todas as APIs de uso geral. Um exemplo prático seria apreciado.

Matt Esch
fonte
Para ajudar os usuários a analisar rapidamente suas perguntas e respostas, considere adicionar suas "Atualizações" como respostas separadas (particularmente a seção "Outra atualização"). Isso é incentivado: blog.stackoverflow.com/2011/07/…
Johann
@ Johann obrigado, agora existem mais atualizações como a resposta aceita para esta pergunta.
Matt Esch

Respostas:

9

A terminologia "verbo" e "substantivo" é um tanto infeliz aqui. Como você já mencionou, você pode criar facilmente objetos para funções. Todas as linguagens orientadas a objetos, exceto Java, têm essa transformação incorporada e, em Java, você acaba fazendo isso o tempo todo, acabando com muitos objetos com um único método e geralmente chamado "invocar", "executar", "aplicar" ou algo assim. (então são as linguagens de programação em que a distinção "verbo" / "substantivo" na verdade não faz sentido).

Os "verbos" do REST são mais como classificar seus métodos para getters, setters (deleters; podem ser considerados tipos de setters) e outros. E tentando fazer tudo com getters e setters. A razão para isso é:

  1. Semântica mais fácil diante da falha de comunicação, pois os getters e os setters são idempotentes. Obter o recurso duas vezes não tem efeito adicional e nem defini-lo com o valor que já possui.
  2. Definindo algumas semânticas que podem ser usadas possivelmente armazenando em cache o proxy que não entende a interface específica. Os getters são armazenados em cache e os setters invalidam o cache.

O HTTP foi projetado desde o início com os caches e a tolerância a falhas em mente; portanto, esses dois pontos levam a quatro métodos básicos:

  • GETé um getter. Supõe-se que não modifique o estado do servidor e retorne o mesmo valor todas as vezes com possibilidade de especificar políticas de expiração e revalidação.
  • PUTe DELETEsão o setter e deleter (= setter com zero). Eles normalmente não são usados ​​no contexto da Web normal, mas fazem sentido para o REST.
  • POST é uma pia de cozinha genérica "invocar" para a qual caches não podem assumir nada.

O REST é um padrão de design que descreve como usar HTTP bruto ou protocolos de rede semelhantes para implementar a interface que permite o fácil gerenciamento de falhas através de novas tentativas simples e funciona bem com proxies de cache.

Não corresponde facilmente à API de programação regular orientada a objetos. Eu acho que é realmente uma coisa boa. Os desafios da interface através da rede, que é inerentemente não confiável e onde as viagens de ida e volta são muito mais lentas do que a transferência de uma quantidade moderada de dados exige uma abordagem de design diferente da API em processo; portanto, quando parece diferente, as pessoas não tentam aplicar experiência inválida do outro domínio tanto (que é a desgraça do SOAP, XML-RPC e tal; parece chamadas de procedimento, mas não funciona assim e acaba sendo difícil de trabalhar).

Jan Hudec
fonte
2

A idéia essencial é que a complexidade seja expressa através da representação de recursos e, portanto, verbos adicionais não são necessários. Como alguns colocaram - "No REST, os substantivos são bons, os verbos são ruins."

Se você observar os quatro verbos REST, eles poderão ser mapeados para as operações básicas de CRUD, permitindo essencialmente que você faça o que quiser com seus recursos. Isso é -

POST - Crie o recurso

GET - Leia o recurso

PUT - Atualize o recurso

DELETE - Exclua o recurso

O que mais você precisa?

Craig Schwarze
fonte
Eu posso facilitar um verbo em um serviço RESTful criando um recurso para fazê-lo. Como você diz, não preciso de verbos adicionais, apenas mais recursos. Só não vejo por que é melhor fingir que qualquer verbo abstrato é um substantivo quando o que eu quero fazer é realmente um verbo. Parece que os verbos são forçados a restringir sem motivo, e estou evitando o problema criando substantivos que executam as ações necessárias quando acessados ​​com um pequeno conjunto de verbos. Por que seria melhor fazer isso? Tem que haver uma boa razão para isso, algo que eu possa quantificar como um exemplo prático.
Matt Esch
4
Obtenha uma lista de todos os recursos, obtenha uma lista de todos os recursos com determinadas restrições, atualize ou exclua vários recursos ao mesmo tempo, crie dois tipos diferentes de recursos juntos atomicamente (para que ambas as criações falhem ou sejam bem-sucedidas), exclua todos os recursos saturando uma dada condição ... A lista de coisas que se pode querer fazer é bastante longa. É possível ajustá-los em uma API REST, mas nem sempre é natural. Também não ajuda que o GET não permita um corpo; portanto, condições de filtragem complexas tornam-se desagradáveis.
187 Andrea Andrea
PATCHing recursos também é muito legal.
amigos estão dizendo sobre watt barnett
2

Considere uma linguagem em que todas as construções (como funções) sejam objetos. Os verbos RESTful estão simplesmente chamando convenções e instruções de atribuição. Para JavaScript, você pode definir uma sintaxe de verbo fixa como INVOKE para chamar uma função, DELETE (o mesmo que excluir em js) para excluir um objeto em outro objeto, SET para atribuir um valor e RETURN para retornar um valor. Poderíamos usar os verbos HTTP para significar a função equivalente de chamada POST, PUT - atribuir valor, GET - retornar um valor, - DELETE - excluir um objeto. Fui pego na ideia de que os métodos HTTP estavam realmente descrevendo métodos de objetos, interfaces de objetos reais, que não consegui descrever que eles realmente descreviam conceitos de nível muito inferior, como as construções básicas da linguagem que são claramente fixas e finitas em todos os aspectos. idiomas sãos.

E é claro que é útil que o roteamento / proxy tenha um vocabulário fixo para refletir.

Matt Esch
fonte
1
  • Porque um programador profissional antecipa centenas, senão milhares de nomes de métodos. O que parece inútil em um pequeno menor pode ser um grande negócio à medida que o aplicativo se torna maior.

  • Porque não há necessidade de padrões sobre nomes de métodos quando eles já estão definidos.

  • Porque o principal objetivo do código é legível sem essas traduções adicionais.

  • Porque incentiva e auxilia na identificação de 'quando' outra classe deve ser dividida.

  • Quando você assume o código, é razoável e realmente possível entender o que e como ele o faz muito mais rapidamente.

  • Ele fornece um vocabulário comum e, portanto, um nível de abstração para que você possa se concentrar em outros detalhes e ver padrões.

  • Isso facilita a localização de bugs, pois códigos e abordagens comuns podem ser facilmente verificados.

  • Quando você trabalha com várias 'camadas', como é o caso do desenvolvimento da Web, saber quais URLs correspondem a quais nomes de ação é muito útil para depuração.

No geral, você nem sempre 'precisa', mas, como a maioria dos padrões, faz muito sentido tentar usá-lo!

Michael Durrant
fonte
Dirigido em ordem 1) Então, um programador antecipa centenas, senão milhares de recursos, caso contrário? Já antecipamos métodos nas bibliotecas que usamos. 2) Então, precisamos de padrões para nomes de métodos, mas não de nomes de recursos? Não consigo seguir essa lógica. 3) Não sei ao certo o que você quer dizer com traduções. Se você me disser que existe um recurso, tenho que entendê-lo. Se eu lhe disser que existe um método, você precisa entendê-lo. A única coisa que realmente importa é que as minhas ações terão efeitos colaterais 4) Você poderia expandir
Matt Esch
5) novamente você pode expandir. Sou programador. Estou acostumado a trabalhar com estruturas de objetos bem definidas. Por que não usaríamos esse mesmo mecanismo para definir todas as nossas APIs, se é realmente melhor? 6) Nenhum nível de abstração vale a pena considerar sem justificativa 7) Novamente você poderia expandir. Se nos beneficiarmos dessa maneira, certamente devemos codificar todas as nossas APIs dessa maneira. 8) Espero que qualquer objeto exponha seus métodos diretamente. / objeto / método não pode ser confundido. Definimos os padrões escolhendo adotá-los. Estou com falta de motivação no momento.
Matt Esch
Matt, você parece um pouco argumentativo, mas eu direi que, para 2) Eu não disse que o recurso não precisaria de padrões 3) Você não precisará entender um método como 'update' ou 'new' or create 'porque você sabe exatamente o que aqueles fazem de acordo com os padrões. No entanto, o que dizer de 'MsgToPrimary', o que isso faz? Criar uma mensagem? Atualizar um status? Enviar um email? 7) Sim, a maioria das APIs poderia se beneficiar disso e muitas o fazem. Eu tentaria focar nos padrões e convenções padrão de noção que são úteis e posso ver que suas atualizações estão mostrando isso.
precisa
Estou apenas tentando entender os benefícios. Os fortes contra-argumentos precisam ser abordados para esclarecer o problema. Ainda entendo que um conjunto fixo de verbos é uma espécie de descrição da linguagem, mas não concordo realmente que isso seja mais fácil de entender. Você não pode tirar um conjunto expressivo de verbos e dizer, ei, agora entendemos todos os verbos, quando não entendemos todos os recursos. Os recursos estão substituindo verbos. Substituímos o verbo arbitrário foo por um recurso chamado foo. Nossa compreensão de foo não é mais clara do que era quando foo era um verbo.
Matt Esch
1

A alternativa é algo horrível: WSDL (também conhecido como Web Service Definition Language), que é uma maneira (desajeitada) de descrever programaticamente (um pouco) APIS arbitrário.

O REST limita severamente os verbos, colocando quase toda a variação específica do aplicativo na carga útil do documento. O benefício de fazer isso é que muitas implementações de clientes podem se comunicar com muitos serviços heterogêneos. Os clientes e servidores podem ser completamente desconhecidos um do outro, alguns ainda não foram gravados.

Há um podcast no qual Stefan Tilkov explica bem o REST .

cbare
fonte
1

Sim, uma API de descanso possui um conjunto fixo de verbos, mas não precisa se limitar a (ou incluir GET, POST, PUT, DELETE). Eu consideraria GET, POST, PUT, DELETE como uma implementação padrão do REST que funciona para 80% de todos os sistemas existentes.

Outros sistemas que estão implementando mais do que operações brutas podem (e fazem) implementar seus próprios verbos para suas APIs REST. Verbos como Publicar, Consumir, Classificar, Comentar, Pesquisar, Procurar podem ser adicionados e implementados em um sistema REST. Enquanto alguns podem dizer que um vocabulário maior pode torná-lo mais complicado, minha resposta é que depende. Se o seu usuário-alvo for um técnico que entenda o que é um POST, sim, pode ser mais complicado; no entanto, se os usuários de destino da sua API são pessoas reais (ou seja, pessoas que não codificam e não sabem o que é um POST), os verbos reais são muito mais fáceis de usar. De fato, ter um conjunto apropriado de verbos para sua API ajuda a manter os URLs curtos (o que é importante se você quiser que os usuários os digitem em um navegador. Se você usa um vocabulário personalizado, você ' gostaria de ter certeza de que sua API e seus verbos estão bem documentados. Ao usar uma API REST customizada, você deseja garantir que suas 'ações somente leitura' sejam um HTTP GET e 'escreva ações' com POST.

A rede social para adolescentes, Piczo.com, (que descanse em paz) apresentava uma API REST estendida (incluindo os verbos mencionados acima) que foi implementada em 7 idiomas diferentes!

Andrew
fonte
0

Simples é bom.

Há casos em que você precisa de verbos e complexidade extras, mas a maioria dos problemas pode ser reduzida a ações CRUD simples em recursos, e é isso que o REST tenta promover. Quando você pensa na maioria dos aplicativos Web, no final, eles lêem e mantêm registros em um armazenamento de dados, que usam as mesmas ações muito simples.

object.foo () é bom, mas o que faz? O que está retornando? Está modificando o estado do objeto ou alguma de suas dependências? Você pode chamá-lo duas vezes e obter o mesmo resultado ou isso lhe dará dois valores diferentes? Se você também tiver object.bar (), eles precisam ser chamados em uma ordem específica?

Há muito conhecimento necessário no uso de uma API avançada, e eles geralmente têm suas próprias convenções (por exemplo, o setFoo vai mudar o objeto, o getBar provavelmente é idempotente, dispose () ou destroy () significa que não há outras chamadas no mesmo objeto será possível, etc ...)

ptyx
fonte