Será que RESTFul é um nome bonito para CRUD? Te disseram que API's RESTFul utilizam substantivos ao invés de verbos? Coisas ao invés de ações? Veja neste post como uma informação mal formulada pode atrapalhar o design de milhares de times.

Funny, there are many cities called Hell on earth  This one was in Grand Cayman.

Os verbos HTTP parecem estar diretamente ligado com o CRUD:

  • Create -> POST
  • Read -> GET
  • Update -> PUT / PATCH
  • Delete -> DELETE

Por causa de uma confusão na classificação de Resource, acabam relacionando REST diretamente a um CRUD. Por causa desse erro de classificação, quem busca criar api's verdadeiramente RESTFul terá dificuldades em seguir as "bases" do conceito.

Resources

Há um senso comum que a classificação de um Resource deve seguir certas regras:

  • Coisa ao invés de ação
  • Substantivos ao invés de verbos

A maioria dos exemplo que encontramos para explicar como classificar um resource, não expöe a complexidade dos objetos. Com exemplos simples. Veja esse:

POST /users # Cria um usuario
PUT /users/{id} # Atualiza o usuario
PATCH  /users/{id} # Parcialmente atualiza o usuario
DELETE /users/{id # Remove o usuario

Perfeito, certo? Utiliza os verbos HTTP de maneira correta. Classificou o recurso como um substantivo. É possivel atualizar, remover, buscar e criar um recurso de usuário.

O problema é que no mundo real, no seu dia a dia, as API's não são tão simples. Elas possuem a complexidade do negócio. Muitas vezes um recurso é um objeto do sistema.

Apenas uma URL para atualizar e mudar seu estado se torna insuficiente. E se ele for um objeto do seu sistema, haverá comportamentos. E é necessário expôr certos comportamentos através da API.

Veja o exemplo abaixo:

POST /candidatos/{id}/submit
POST /candidatos/{id}/approve
POST /candidatos/{id}/decline
POST /candidatos/{id}/transfer

O resource candidatos possui comportamentos distintos. O approve pode, por exemplo, disparar um Evento que é capturado por outro sistema. Que por usa vez, vai disparar um e-mail para o RH.

O transfer pode gerar um fluxo de aprovação com outro gestor para aceitar a transferência do candidato.

O REST nunca limitou o Resource a substantivos sem acões.

REST é sobre Resource

O artigo de Roy Fielding não especifica que a classificação de um Resource segue essas regras. Pelo contrário, o artigo menciona que um Resource é qualquer coisa que possa ser identificada.

A RFC 3986 vai de encontro ao artigo de Roy, resource é qualquer coisa que possa ser identificada através de uma URI.

This specification does not limit the scope of what might be a
resource; rather, the term "resource" is used in a general sense
for whatever might be identified by a URI. Familiar examples
include an electronic document, an image, a source of information
with a consistent purpose (e.g., "today's weather report for Los
Angeles"), a service (e.g., an HTTP-to-SMS gateway), and a
collection of other resources.
Uniform Resource Identifier (URI): Generic Syntax - RFC 3986

Logo uma ação é perfeitamente identificável. candidato/{id}/aprrove é um resource único, identificável e com uma URI. Além disso ele deixa claro a ação que será feita em conjunto com os verbos HTTP.

Dicas e sugestões

Não há um guia oficial sobre as melhores praticas de projetar as APIs. Logo as sugestões abaixo estão baseadas em um consenso do que são boas práticas.

  1. Respeitar os verbos HTTP em primeiro lugar.
HTTP Method Seguro Semantica
OPTIONS Sim Busca os metodos http válidos e outras opções
GET Sim Busca um resource
HEAD Sim Busca apenas o header de um resource
PUT Não Atualiza um resource
POST Não Cria um resource
DELETE Não Remove um resource
PATCH Não Atualiza parcialmente um resource

Utilizar ações apenas após definir uma URI para um resource, desde que a ação não sobrescreva o sentido do verbo HTTP, por exemplo, POST /usuarios/criar. Neste caso basta o verbo HTTP, POST /usuarios.

A ação deve estar ligado a um requisito de negócio. Deve ser clara, POST /usuarios/2/solicitar-ferias. Esse tipo de cenário pode ser utilizado em conjunto com o CQRS. Na Controller o método pode esperar um objeto de tipo SolicitarFeriasCommand.

O time ganha liberdade para fazer design melhores, oferecendo recursos que não São baseados em CRUD. E sem ferir o padrão REST.

Conclusão

O REST é um conceito bem estabelecido no mercado. Infelizmente por uma falta de entendimento do conceito de Resource direciona times de desenvolvimento a perder horas de discussão sobre como prover um determinado serviço sem quebrar o padrão RESTFul.

Espero que tenha ajudado vocês!

Referências