Específicos · Engenharia de Software
REST: restrições, HATEOAS, Richardson; GraphQL: query/mutation, over/under-fetching
REST é um conjunto de seis restrições, não um protocolo. A mais cobrada é a ausência de estado: 5 dos 14 itens — e em quatro deles a banca a enuncia certo, e o item é Certo.
Altíssima14 itens no tópico
A ideia que organiza o assunto
REST não é tecnologia, não é padrão publicado por comitê e não é sinônimo de “API com JSON”. É um estilo arquitetural: um conjunto de restrições que Roy Fielding descreveu na tese de doutorado de 2000, ao explicar por que a web escalou. Cada restrição é uma renúncia deliberada — abre-se mão de alguma liberdade de projeto para ganhar uma propriedade do sistema. Abrir mão de guardar sessão no servidor compra escalabilidade horizontal; abrir mão de o cliente saber com quem fala compra a liberdade de pôr proxy, cache e balanceador no caminho.
Daí a maneira correta de ler qualquer item deste tópico: pergunte qual restrição ele está afirmando ou negando, e o que essa restrição existe para permitir. Um item que diz que REST não admite servidores intermediários está negando a restrição de sistema em camadas — que existe justamente para admiti-los. Um item que diz que a API deve ser stateful está negando a restrição que é a mais cobrada de todas.
Porque há uma assimetria grande na prova. Das seis restrições, ausência de estado é a mais cobrada — aparece em 5 dos 14 itens medidos, mais que qualquer outra —, e quase sempre na mesma formulação: cada solicitação deve conter todas as informações necessárias, independentemente do que esteja armazenado no servidor. Quando o item traz essa frase, é certo — e é assim que ela aparece em quatro dos cinco; quando traz sessão, contexto guardado ou informação preservada entre chamadas, é errado. Reconhecer as duas metades desse par resolve a maior fatia do tópico.
O restante se divide em dois formatos menores. Um é a interface uniforme: recurso identificado por endereço próprio, operação dada pelo verbo HTTP — e não por porta, por parâmetro ou por nome de método no corpo da mensagem, que é como o SOAP trabalha. O outro é a etiqueta do GraphQL, uma tecnologia cujo nome convida a três interpretações erradas ao mesmo tempo: banco de grafos, gráficos e SQL. Nenhuma delas é o que ele é.
Por que se usa (e o que custa)
REST venceu o SOAP porque cobra menos. Não há envelope, não há contrato WSDL obrigatório, não há ferramenta de geração de stub: basta HTTP, que todo cliente já fala, e uma representação que todo cliente já sabe ler. Como o servidor não guarda sessão, qualquer instância atende qualquer requisição, e escalar é acrescentar máquina atrás do balanceador. Como o GET é seguro e idempotente, a resposta é cacheável por qualquer intermediário — e essa é a propriedade que sustenta a web inteira.
Paga-se em três moedas. A ausência de estado obriga o cliente a reenviar autenticação e contexto a cada chamada, o que aumenta o tráfego e transfere responsabilidade para ele. A modelagem por recurso é confortável para operação de CRUD e desconfortável para operação que não é substantivo — transferir, aprovar, cancelar viram ginástica de nomeação. E o desenho orientado a recurso produz busca excessiva e busca insuficiente: o endpoint devolve campos que aquela tela não usa, ou a tela precisa de três chamadas encadeadas para montar o que mostra.
É exatamente esse último custo que o GraphQL ataca. Com ponto de entrada único e esquema tipado, o cliente descreve a forma dos dados que quer e recebe isso e nada mais, em uma só ida ao servidor. O que se paga em troca: perde-se o cache de HTTP, porque tudo passa a ser um POST para o mesmo endereço; perde-se a semântica de código de status, porque o GraphQL responde 200 com um campo de erros dentro; e ganha-se um custo de consulta que o cliente controla, o que obriga o servidor a limitar profundidade e complexidade para não ser derrubado por uma consulta aninhada.
A formulação honesta para a prova: REST entrega simplicidade, cache e escala e cobra em número de chamadas e em dados trafegados a mais; GraphQL entrega precisão de consulta e cobra em cache, em observabilidade e em controle de custo.
Como funciona
As seis restrições, cinco obrigatórias e uma opcional:
- Cliente-servidor — separa interface de armazenamento, e permite que os dois lados evoluam independentemente.
- Ausência de estado (stateless) — nenhuma sessão no servidor entre requisições; toda requisição chega autocontida.
- Cache — a resposta declara se pode ser reaproveitada, e por quanto tempo.
- Interface uniforme — a restrição central, detalhada abaixo.
- Sistema em camadas — o cliente não sabe se fala com a origem ou com um intermediário; é o que autoriza proxy, gateway, cache e balanceador.
- Código sob demanda — o servidor pode enviar código executável ao cliente. É a única opcional.
A interface uniforme tem, por sua vez, quatro sub-restrições, e é nelas que mora o desenho de uma API RESTful: identificação do recurso por URI; manipulação do recurso por meio de representações (JSON, XML, HTML, o que a negociação de conteúdo definir); mensagens autodescritivas, em que o método, os cabeçalhos e o tipo de mídia bastam para processar a requisição; e HATEOAS.
HATEOAS — hypermedia as the engine of application state — é a sub-restrição que quase nenhuma API implementa. Saiba-a pelo nome, mas com a ressalva medida: nenhum item deste corpus a cobra. A ideia: a resposta não traz só os dados do recurso, traz também os links para os próximos passos possíveis a partir do estado atual. Um pedido em aberto vem com o link para pagar e para cancelar; o mesmo pedido já pago vem sem o link de pagar e com o de acompanhar a entrega. O cliente navega pelos links que recebe, como um navegador navega por páginas, em vez de montar endereços a partir de documentação fixa. A propriedade que isso compra é desacoplamento: o servidor muda os endereços sem quebrar o cliente.
O modelo de maturidade de Richardson organiza o caminho até lá em quatro níveis, e existe justamente para mostrar que a maioria das APIs chamadas de REST para no nível 2:
| nível | o que acrescenta |
|---|---|
| 0 | HTTP como túnel: um endereço único, tudo por POST — é o desenho do SOAP |
| 1 | recursos: cada coisa ganha o seu próprio endereço |
| 2 | verbos HTTP e códigos de status com a semântica correta |
| 3 | HATEOAS: as respostas trazem os links dos próximos passos |
Nenhum item medido do tópico menciona Richardson ou os seus níveis. A tabela está aqui porque é o vocabulário canônico do estilo, não porque já tenha decidido item.
Os métodos, pelas duas propriedades que decidem item. Seguro é o método que não altera o recurso; idempotente é aquele cuja repetição produz o mesmo efeito da primeira vez. GET, HEAD, OPTIONS e TRACE são seguros e idempotentes. PUT e DELETE são idempotentes e não seguros — repetir um DELETE deixa o recurso igualmente ausente, ainda que a segunda resposta seja 404. POST não é nem uma coisa nem outra, e PATCH é idempotente apenas se o corpo for escrito de forma a sê-lo.
GraphQL, em quatro frases. É uma linguagem de consulta para APIs, com esquema fortemente tipado declarado no servidor. Expõe um único ponto de entrada, em vez de um endereço por recurso. Tem três tipos de operação — query para ler, mutation para alterar, subscription para receber atualizações — e o cliente recebe exatamente os campos que pediu, nem mais nem menos. Quem efetivamente busca os dados são os resolvedores escritos no servidor: são eles que falam com o banco, com outro serviço ou com uma API REST. O graph do nome é o grafo do esquema — tipos ligados por campos —, e não grafo armazenado em banco.
O que decide os itens
Stateless, nas duas direções — o par mais cobrado do tópico:
| o item diz… | veredito |
|---|---|
| cada requisição contém tudo o que é necessário | certo |
| o servidor atende independentemente das requisições anteriores | certo |
| as requisições são separadas e desconectadas entre si | certo |
| o servidor mantém sessão / contexto entre chamadas | errado |
| as informações do cliente são armazenadas entre solicitações | errado |
| a comunicação é stateful | errado |
Cuidado com o falso par: stateless não quer dizer ausência de autenticação. O token viaja em toda requisição porque o servidor não guarda sessão.
Restrição → o que ela autoriza — a leitura que resolve os itens de negação:
| restrição | existe para permitir |
|---|---|
| cliente-servidor | evolução independente dos dois lados |
| ausência de estado | escala horizontal, qualquer instância atende |
| cache | reaproveitamento da resposta por intermediários |
| interface uniforme | cliente genérico, sem contrato proprietário |
| sistema em camadas | proxy, gateway, cache e balanceador no caminho |
| código sob demanda | estender o cliente — e é a única opcional |
Como se identifica a operação:
| REST | SOAP | |
|---|---|---|
| endereço | um por recurso | um único endpoint |
| operação | método HTTP | nome da operação no envelope |
| formato | JSON, XML, HTML, texto… | XML obrigatório |
| contrato | OpenAPI, opcional | WSDL |
| porta | a mesma para todo o serviço | a mesma |
A porta nunca seleciona a operação. Item que faça a porta distinguir método trocou a camada de transporte pela de aplicação.
URI × URL × URN — a banca ataca pela expansão da sigla:
| sigla | é |
|---|---|
| URI (uniform resource identifier) | o identificador; é a palavra da especificação REST |
| URL (uniform resource locator) | espécie de URI que também informa localização e forma de acesso |
| URN (uniform resource name) | espécie de URI que apenas nomeia, sem localizar |
REST × GraphQL:
| REST | GraphQL | |
|---|---|---|
| pontos de entrada | um por recurso | um só |
| o que volta | o que o endpoint define | o que o cliente pediu |
| busca excessiva / insuficiente | frequente | resolvida por desenho |
| cache HTTP | nativo no GET | perdido (POST único) |
| erro | código de status | 200 com campo errors |
| acesso ao banco | pela aplicação | pelos resolvedores |
O que o GraphQL não é: não é banco de dados, não consulta grafo armazenado, não executa SQL contra o SGBD, não tem relação com gráficos e não substitui a camada de persistência.
Conflito e concorrência não se resolvem sozinhos. O URI identifica um único
recurso; quando há disputa sobre o mesmo recurso, quem trata é a aplicação, que
sinaliza com 409 Conflict, apoiada em ETag e If-Match no controle otimista.
Item que prometa resolução automática pelo web service generalizou.
Números que caem
Aviso de honestidade: nenhum dos 14 itens medidos deste tópico se decidiu por um destes números. A tabela é preparação para o que a banca pode cobrar, não retrato do que ela cobrou.
| restrições do REST | 6, sendo 5 obrigatórias e 1 opcional (código sob demanda) |
| sub-restrições da interface uniforme | 4 (URI, representações, mensagens autodescritivas, HATEOAS) |
| níveis de maturidade de Richardson | 0 a 3; HATEOAS é o nível 3 |
| tese de Fielding | 2000, capítulo 5 |
| métodos seguros e idempotentes | 4: GET, HEAD, OPTIONS, TRACE |
| métodos idempotentes e não seguros | 2: PUT, DELETE |
| método nem seguro nem idempotente | 1: POST |
| tipos de operação do GraphQL | 3: query, mutation, subscription |
| status de conflito de recurso | 409 |
| status devolvido pelo GraphQL em erro de negócio | 200, com o erro no corpo |
Como a CEBRASPE derruba você aqui
Medido sobre os 14 itens do tópico: 6 Certo e 8 Errado. Catorze itens não produzem frequência, só direção — aqui se conta, não se calcula percentual. E a contagem corrige de saída a intuição mais comum sobre o tópico: a restrição mais cobrada quase nunca é a que derruba. Ausência de estado aparece em 5 dos 14 itens, mais que qualquer outra, e em quatro deles a banca a enuncia corretamente e o item é Certo — “cada solicitação do cliente para o servidor deve conter todas as informações necessárias”, “o servidor completará cada solicitação (…) independentemente de todas as solicitações anteriores”, “as interações acontecem sem controle de estado”. Só um a inverte. Quem aprendeu que “stateless é pegadinha” erra quatro itens fáceis para acertar um.
Registre também o que não está aqui. HATEOAS não aparece em nenhum dos 14 itens. O modelo de maturidade de Richardson, tampouco. Nem a distinção entre métodos seguros e idempotentes, nem a restrição de cache, nem código sob demanda. Isso não autoriza ignorá-los — são o vocabulário canônico do estilo e a banca pode cobrá-los amanhã —, mas nada neste corpus foi decidido por eles, e estudá-los antes das seis restrições e do par REST × SOAP é inverter a ordem de prioridade.
Os oito itens errados formam três pares e dois avulsos.
REST descrito com os traços do SOAP — 2 dos 8. “todos os métodos são identificados pela mesma URL, sendo cada método acionado por uma porta específica”: endereço único é o desenho do SOAP, e a porta é transporte, nunca seletor de operação. “os dados são retornados exclusivamente no formato XML”: quem obriga XML é o envelope do SOAP; no REST o formato vem da negociação de conteúdo. A defesa é a mesma nos dois: quando o item impuser endereço único, formato único ou operação fora do verbo HTTP, ele está descrevendo o vizinho. E vale a comparação com o item Certo que usa as mesmas palavras — “cada método é identificado por uma URL única” —, onde a unicidade está do lado certo.
GraphQL colado ao banco de dados — 2 dos 8, e são os dois únicos itens de GraphQL do corpus. “utilizada para consulta a objetos gráficos em bancos de dados relacionais” e “a GraphQL executa comandos SQL em arquiteturas RESTful diretamente no(s) SGBD”. Os dois erram pela mesma porta: fazem uma linguagem de consulta de API falar direto com o banco. Todo item de GraphQL medido aqui é errado, e todos erram nesse ponto — quem consulta o SGBD é o resolvedor escrito no servidor, e o graph do nome é o grafo do esquema.
Uma restrição negada — 2 dos 8. “devem ter uma comunicação statefull entre cliente e servidor, na qual as informações do cliente são armazenadas entre solicitações GET distintas” nega a ausência de estado. “A arquitetura RESTful não possibilita o uso de servidores intermediários, chamados de balanceadores de carga” nega o sistema em camadas — que existe precisamente para autorizar proxy, gateway, cache e balanceador. O teste: a proibição enunciada corresponde a alguma permissão de alguma das seis restrições? Se corresponder, o item está invertido.
Automatismo prometido — 1 dos 8. “os conflitos decorrentes de recursos que tenham identificadores iguais são automaticamente resolvidos no web service” atribui ao estilo arquitetural a solução de um problema de aplicação. Automaticamente, transparentemente e sem intervenção são palavras de risco; a existência de um código de status próprio — o 409 — já mostra que alguém tem de tratar a situação.
Expansão de sigla como isca — 1 dos 8. “por meio de URL (uniform resource locator)”: a expansão entre parênteses é o alvo, porque a palavra da especificação é URI. Sempre que a banca escrever a sigla por extenso, confira a expansão antes do resto da frase.
Erros clássicos
Chamar REST de protocolo. É estilo arquitetural. O protocolo é o HTTP, que REST usa — e, em tese, o estilo não está preso a ele.
Confundir stateless com ausência de estado no sistema. O recurso continua tendo estado persistido no banco. O que não existe é estado de sessão no servidor entre duas requisições.
Achar que RESTful obriga JSON. JSON predomina, mas o formato é negociado, e XML, HTML, texto e binário são igualmente legítimos.
Confundir seguro com idempotente. Seguro é não alterar; idempotente é a repetição não somar efeito. DELETE é idempotente e não é seguro.
Achar que POST é idempotente. Não é: dois POST iguais criam dois recursos. É o único método do conjunto que não é seguro nem idempotente.
Tratar código sob demanda como obrigatório. É a única das seis restrições que é opcional.
Chamar de REST maduro uma API que para no nível 2. Sem HATEOAS, o nível de Richardson é 2 — e é onde quase toda API de mercado fica.
Achar que HATEOAS é documentação. É o contrário: a documentação externa é o que HATEOAS pretende substituir, entregando os próximos passos como links na própria resposta.
Achar que GraphQL substitui o banco de dados. Ele fica entre o cliente e o servidor de aplicação; o acesso ao dado continua sendo dos resolvedores.
Esperar código de status de erro do GraphQL. A resposta costuma vir 200, com
o problema descrito no campo errors do corpo.
LidoPraticado