1 pontos por GN⁺ 2025-01-24 | 1 comentários | Compartilhar no WhatsApp
  • O ponto de partida do design de APIs é a diferença entre RPC e REST; as três abordagens podem se conectar ao HTTP, mas diferem no modelo de como as chamadas são feitas e de como os clientes são construídos
  • REST é um modelo de hipertexto no qual se seguem as URLs fornecidas pelo servidor, o que o diferencia de APIs no estilo OpenAPI, em que o cliente monta formatos de URL
  • OpenAPI define operações com templates de caminho de URL e métodos HTTP, sendo prática e amplamente usada, mas mais próxima de um modelo RPC mapeado para HTTP do que de REST
  • gRPC define APIs RPC diretamente por meio de IDL, geração de código, payload binário e gerenciamento de conexão HTTP/2, ocultando os detalhes de HTTP
  • O gRPC exige software especializado dos dois lados e tem limitações em reforço por proxy, prevenção de atualizações concorrentes e atualizações parciais; por isso, é especialmente adequado para APIs internas ou quando se pode usar uma camada de conversão como o Cloud Endpoints

Três modelos para enxergar APIs baseadas em HTTP

  • As principais abordagens que usam HTTP como camada de transporte para APIs se dividem em REST, OpenAPI e gRPC
  • Um dos motivos de muitas APIs públicas e APIs distribuídas privadas usarem HTTP é que as organizações já estão acostumadas com as questões de segurança do tráfego HTTP nas portas 80 e 443
  • As três abordagens podem se conectar ao HTTP, mas diferem no que tomam como endereçamento e em como o cliente constrói as chamadas

REST: seguir URLs em vez de montá-las

  • Em REST, o cliente usa exatamente as URLs fornecidas pelo servidor e não entende nem monta o formato da URL como parte da especificação da API
  • O navegador segue a página atual, favoritos e URLs digitadas pelo usuário, fazendo no máximo a extração de informações da requisição HTTP a partir da URL ou convertendo URLs relativas em URLs absolutas
  • O núcleo de uma API REST é o uso de hipertexto/hipermídia que expressa referências entre recursos como URLs de outros recursos
  • Na abordagem REST, todos os identificadores são trocados como URLs
    • POST /accountsaccount_URL
    • enviar account_URL em POST /subscriptionssubscription_URL
    • GET {account_URL} → retorna a árvore de dados da conta
  • A vantagem de REST está em sua proximidade com a estabilidade, consistência e universalidade da própria web, e o modelo orientado a entidades de HTTP/REST pode tornar a API mais simples e regular

OpenAPI: mais próxima de RPC mapeado diretamente para HTTP

  • OpenAPI define templates de caminho de URL em paths, e chama a combinação de caminho e método HTTP de operação (operation)
  • Um caminho como /pets/{petId} exige que o cliente conheça o valor de {petId} e o insira no template de URL para montar a requisição HTTP
  • Nessa abordagem, o cliente precisa conhecer em detalhes o formato da URL, o que é o oposto do modelo de hipertexto de REST
  • Os motivos de OpenAPI ser amplamente usada são claros
    • É parecida com o tradicional modelo RPC, algo familiar para programadores
    • É possível mapear diretamente os conceitos de RPC para requisições HTTP
  • Em APIs públicas, a grande vantagem é poder acessar a API em praticamente qualquer linguagem e ambiente usando apenas tecnologias HTTP padrão
  • Em contrapartida, é preciso projetar caminhos de URL, métodos HTTP e mapeamento de parâmetros, aumentando os detalhes que tanto provedores quanto consumidores da API precisam aprender

gRPC: tecnologia de implementação de RPC que esconde o HTTP/2

  • gRPC usa HTTP/2 como camada de transporte, mas não expõe os detalhes de HTTP aos projetistas da API nem ao código de cliente e servidor
  • O fluxo de chamada no cliente gRPC é simples
    • decidir qual procedimento chamar
    • calcular os valores de parâmetros a usar
    • passar os parâmetros ao stub gerado por código e fazer a chamada
  • gRPC define procedimentos remotos com base em interface description language, então, diferentemente de OpenAPI, não é necessário expressar junto o mapeamento de caminho de URL, parâmetros e métodos HTTP
  • Por meio de geração de código, frameworks e bibliotecas, pode ser mais fácil criar bibliotecas cliente e implementações de servidor
  • Há vantagens de desempenho com payloads binários e gerenciamento de conexão HTTP/2; também é possível usar as mesmas tecnologias diretamente sem gRPC, mas isso exige aprender mais tecnologia

Quando considerar gRPC em vez de OpenAPI

  • Ao projetar uma API com OpenAPI, é preciso expressar operações e parâmetros como combinação de caminhos de URL e métodos HTTP, e a quantidade de escolhas pode tornar isso trabalhoso
  • Se você vai continuar usando um modelo no estilo RPC, o gRPC reduz o peso de ter de projetar manualmente um mapeamento personalizado para HTTP
  • gRPC e OpenAPI têm modelos básicos de API parecidos, mas diferem na forma de expor HTTP
    • OpenAPI expõe os detalhes de transporte HTTP ao cliente e permite ao projetista controlar o mapeamento
    • gRPC oculta os detalhes de HTTP por meio de mapeamentos predefinidos e código gerado
  • A grande vantagem de OpenAPI é que o cliente pode usar diretamente ferramentas e tecnologias HTTP padrão, e para muitos projetistas de API isso justifica o custo extra de design

Combinando RPC com um modelo orientado a entidades

  • Mesmo usando gRPC ou OpenAPI, é possível obter algumas vantagens de REST se os métodos RPC forem limitados a um foco em entidades
  • A abordagem consiste em definir primeiro os tipos de recurso, em vez de começar pela definição dos procedimentos, e então associar a cada tipo as operações padrão sobre entidades
  • As operações básicas são Create, Retrieve, Update, Delete e List, frequentemente vistas como CRUD plus List
  • Operações adicionais podem ser incluídas quando necessário, mas misturar conceitos orientados a entidades com conceitos orientados a procedimentos pode enfraquecer parte dessas vantagens
  • Agrupar procedimentos por tipo de entidade também é uma das ideias centrais das linguagens orientadas a objetos

Limitações e pontos de atenção do gRPC

  • gRPC exige software especializado tanto no cliente quanto no servidor, e o código gerado precisa ser integrado ao processo de build de ambos os lados
  • Para usuários de linguagens dinâmicas como JavaScript ou Python, onde o ambiente de desenvolvimento pode quase não ter processo de build, essa exigência pode ser um peso
  • O Google Cloud Endpoints permite acessar APIs gRPC via HTTP e JSON, restaurando opções para o cliente, mas nem todos os usuários podem adotá-lo ou construir algo equivalente
  • Em APIs REST, é fácil criar bots que rastreiem tudo sem metadados; já APIs no estilo RPC, como gRPC ou OpenAPI, exigem APIs diferentes por tipo de entidade e metadados ou software personalizado
  • APIs HTTP frequentemente recebem recursos adicionais por meio de ferramentas de gestão de API e proxies, como Apigee Edge, incluindo segurança, validação de entrada, mapeamento de formato de dados e modificação de cabeçalhos e corpo; no gRPC, esse tipo de reforço por proxy pode ser muito mais difícil
  • gRPC não define um mecanismo padrão para evitar perda de dados causada por atualizações concorrentes
    • HTTP fornece os cabeçalhos Etag e If-Match para isso
  • gRPC também não define um mecanismo de atualização parcial
    • HTTP tem PATCH, e para JSON há os padrões JSON merge patch e JSON patch
    • JSON merge patch é mais simples, mas não consegue tratar todos os casos, como atualização de arrays
    • JSON patch cobre mais casos, mas é mais complexo de usar

Critérios de escolha

  • Se você já sabe projetar com o modelo de hipertexto de REST, ou está disposto a aprendê-lo, ele pode ser uma boa escolha para buscar estabilidade, consistência e universalidade
  • OpenAPI permite criar APIs acessíveis com tecnologias HTTP padrão, mas o aumento das escolhas de design para mapear conceitos de RPC em HTTP pode dificultar projeto, implementação e aprendizado
  • Se uma API está sendo considerada para OpenAPI, vale também avaliar gRPC. O modelo básico de API dos dois é comparável, e o gRPC reduz a necessidade de criar manualmente o mapeamento HTTP
  • gRPC é especialmente atraente nas seguintes condições
    • quando produtos como Cloud Endpoints permitem que o cliente não precise adotar obrigatoriamente a tecnologia gRPC
    • quando se trata de uma API interna, na qual é possível controlar as escolhas tecnológicas do servidor e de todos os clientes
  • Ao adotar gRPC no lugar de OpenAPI ou REST, é preciso considerar que as oportunidades de reforçar ou corrigir o comportamento da API com proxies baseados em ferramentas de gestão de API, como Apigee Edge, podem ficar muito mais limitadas

1 comentários

 
GN⁺ 2025-01-24
Opiniões no Hacker News
  • Se eu pudesse voltar no tempo, teria impedido a mim mesmo de aprender gRPC desde o início
    No começo, fiquei encantado com a visão, mas depois de alguns anos vi que havia problemas demais. A ideia de que ele esconde os detalhes internos chega a ser uma piada; para descobrir a causa de uma requisição que falha 1 vez em 10, você acaba despejando logs de debug e ajustando de 10 a 20 configurações de timeout/retry com nomes ambíguos
    Plugins do Maven, estranhos deadline exceeded, load balancers que não gostam de HTTP/2, situações em que você acaba tendo de usar uma API padrão por causa de firewalls, documentação fraca e até conseguir mensagens de erro úteis para observabilidade — tudo isso consome tempo

    • O problema do gRPC não está tanto no protocolo ou no protobuf em si, mas no fato de que, pelo menos no toolchain de Java, ele é péssimo
      A experiência de desenvolvimento do código gerado é ruim, os stubs de cliente são classes concretas final, difíceis de mockar em testes, e a implementação do servidor também precisa herdar de uma classe concreta em vez de implementar uma interface
      Os métodos do servidor têm assinaturas assíncronas, o que quebra comportamentos baseados em AOP como @Transactional; também não há suporte a exceções e, embora classes de valor imutáveis sejam boas, tudo precisa ser criado via builders
      No fim, para usar gRPC em SOA, é preciso escrever bastante código de encanamento para esconder o ruído do gRPC e obter código limpo e testável; o compilador RPC do Thrift também tem problemas parecidos, além de outros
    • Esses problemas parecem estar mais ligados a implementações específicas do que à própria especificação gRPC/protobuf
      Em .NET e C# modernos, a experiência com gRPC é bem boa, tanto que a Microsoft encerrou tecnologias RPC anteriores, como WCF, e passou a focar em gRPC
    • O maior projeto em que usei isso foi em Java, e validar a saída dos bindings gerados pelo protoc era mais verboso e mais propenso a erros do que serializar manualmente
      O protocolo no fio não é type-safe; ele tem tags de tipo, mas reutiliza a mesma tag para vários tipos de dados. A codificação de inteiros zig-zag também é lenta
      Como biblioteca RPC, é péssima, e a única coisa pior que experimentei foi FlatBuffers
    • Pelo fato de mencionar Maven, parece que você usa Java; da minha perspectiva, programando em Go nos últimos 8 anos mais ou menos, a experiência com gRPC é bem diferente
      Fico curioso se essa diferença se deve ao Java ou à própria tecnologia gRPC
    • Uso gRPC há alguns anos em uma stack Go+Dart e nunca passei por esses problemas
      Fico me perguntando se são problemas específicos de Java+gRPC
  • Crio APIs há muito tempo, já usei tanto gRPC quanto HTTP/REST, e também publiquei a biblioteca https://github.com/oapi-codegen/oapi-codegen, que gera clientes e servidores em Go a partir de especificações OpenAPI
    É difícil concordar com a forma como o texto separa OpenAPI de REST. OpenAPI é uma maneira de documentar o comportamento de uma API HTTP, e pode representar tanto uma API RESTful quanto uma API completamente arbitrária. No sentido de ser uma linguagem de esquema que descreve a API de uma forma que ferramentas conseguem interpretar, ela é conceitualmente parecida com um arquivo Protocol Buffer que especifica um protocolo gRPC
    gRPC é um mecanismo de RPC que troca protos; quando o Google abriu o protobuf, não abriu sua camada interna de RPC, a Stubby, e o gRPC não é tão bom quanto a Stubby. Ainda assim, a eficiência de transporte é alta e ele também é relativamente fácil de estender
    Porém, o gRPC não tem um ecossistema tão robusto quanto as bibliotecas HTTP mais populares, então muitas vezes é preciso implementar por conta própria middlewares como logging ou autenticação, especialmente em RPC entre serviços implementados em linguagens diferentes
    Vejo que o verdadeiro problema do gRPC são os arquivos proto. Como todos os clientes precisam ser compilados com arquivos .proto compatíveis com o servidor, não é um protocolo descobrível. Uma API HTTP pode ser chamada com curl ou com código escrito manualmente mesmo sem uma descrição OpenAPI, o que deixa o acoplamento mais frouxo e, por isso, facilita o trabalho e a depuração

    • Há uma distinção entre o que este blog chama de “OpenAPI” e REST de fato. Só que, na prática, quase ninguém cria APIs REST de verdade; a maioria usa uma abordagem no estilo OpenAPI
      REST, como definido na tese de doutorado de Roy Fielding em 2000, pressupunha que, ao fazer um GET na URL raiz, haveria links dentro da resposta 200 OK, e que seria possível explorar todos os recursos oferecidos pela API seguindo esses links. Estruturas hierárquicas eram permitidas, mas tudo precisava ser acessível em algum ponto da árvore de links; a intenção era oferecer capacidade de descoberta
      Em praticamente todos os lugares em que trabalhei nos últimos 20 anos, usava-se POST resource_name/resource_id/sub_resource/sub_resource_id/mutation_type ou, dependendo da forma da empresa lidar com idempotência, PUT resource_name/resource_id/sub_resource/sub_resource_id, e o cliente montava URLs mágicas com base em conhecimento estrutural como Swagger/OpenAPI
      Por isso, pessoas mais rigorosas costumam chamar a prática do mercado de “RESTful”, e não de “REST”, para indicar que ela não implementa a definição de REST de Fielding
    • A parte que distingue OpenAPI de REST também me deixou confuso. O que o texto chama de REST parece mais próximo de HATEOAS
      Da perspectiva de quem gerencia APIs bem grandes com clientes internos/externos, também acho difícil entender o fluxo de gerar código a partir de uma especificação OpenAPI. Você preenche os stubs gerados e depois vai refinando iterativamente a especificação da API; então a ferramenta gera novos stubs de novo, passa a ser necessário fazer merges manuais e, conforme a API cresce, fica difícil encontrar as alterações relacionadas
      Por isso criei um monstro que gera especificações OpenAPI a partir do código usando go/ast e afins. Não é perfeito, mas é uma solução de 95% que funciona tanto com Echo quanto com Gin; quando preciso de um novo endpoint, crio as structs de requisição/resposta e um handler vazio, gero a documentação e envio para o desenvolvedor de frontend, conseguindo avançar rapidamente
      A maioria dos desenvolvedores não precisa se preocupar em como representar a API em OpenAPI, e a documentação fica sempre alinhada ao código
    • Hoje em dia existe gRPC reflection para descoberta: https://grpc.io/docs/guides/reflection/
    • Também estou usando especificações OpenAPI para criar, junto com tipos gerados, uma sintaxe de consulta parecida com SQL. Assim, dá para lidar com qualquer API de terceiros com a mesma sensação
      Apipe.new(GitHun) |> from("search/repositories") |> eq(:language, "elixir") |> order_by(:updated) |> limit(1) |> execute()
      Não é preciso conhecer as funções gRPC disponíveis nem as peculiaridades RESTful de APIs de terceiros, e ainda é possível manter documentação embutida e acesso a tipos
      https://github.com/cpursley/apipe
      Também estou considerando uma camada adaptadora em TypeScript para que possa ser inserida em projetos JS/TS como o Supabase
      const { data, error } = await apipe.from('search/repositories').eq('language', 'elixir').order_by('updated').limit(1)
      Essa chamada pode passar por um proxy em Elixir, deixando que ele cuide de tarefas pesadas como processamento assíncrono ou limitação de taxa
    • Dizer que o gRPC não é um protocolo descobrível não é totalmente correto
      É possível criar uma descrição OpenAPI com base na serialização JSON do Protobuf e servi-la via Swagger, e o próprio gRPC também oferece reflection embutido e o utilitário grpcurl, que a utiliza
  • Da perspectiva de quem já trabalhou em algumas FAANG, Thrift/gRPC é realmente útil para roteamento de serviços internos
    Só que uma boa parte dessa complexidade é gerenciada pelas equipes que criam bibliotecas, camadas de descoberta de serviços, roteamento etc. Usar um protocolo RPC permite fazer esse tipo de coisa em uma escala e velocidade difíceis de alcançar com serviços JSON/REST comuns
    Nunca vi uma REST API que não deixasse verbos “vazarem”, e, se eu tivesse que criar uma malha de serviços de backend ou conectar dois serviços locais por meio de um stream de rede, eu sempre escolheria gRPC
    Mas eu jamais usaria gRPC para algo exposto a clientes ou à web. RPC é poderoso porque fixa muitas decisões e força “um único jeito” de fazer as coisas. Por outro lado, se vários clientes em diferentes stacks tecnológicas precisam usar o serviço, REST é muito melhor

    • Eu não faria isso em uma API pública, mas em APIs privadas simplesmente trato como POST /api/doThingy com um corpo JSON
      É um RPC fácil em que qualquer pessoa pode participar tendo apenas o cliente HTTP mais básico, e funciona bem em todos os sistemas operacionais e navegadores. Também não é preciso ficar brigando para decidir se algo vai no caminho da URL, nos parâmetros de consulta ou no corpo
      Se você usar uma família de servidores que tenta tornar isso menos incômodo, como Buf ou Connect, o gRPC também aceita de bom grado JSON via HTTP
    • Fico curioso sobre aplicações cliente/servidor que não são web
      Penso em casos como jogos online ou MMOs, que precisam de comunicação muito mais em tempo real do que REST, mas não sei bem se hoje em dia as pessoas colocam alguma coisa em cima de uma conexão por socket
    • Se Thrift/gRPC é uma bênção no roteamento de serviços internos, fico curioso: em comparação com o quê?
      Também gostaria de saber que outras alternativas foram tentadas
    • Fico curioso sobre o que significa “verbos vazarem”
  • Se você não está fazendo streaming bidirecional, em geral vejo gRPC como perda de tempo
    Há o inferno de dependências transitivas em tempo de execução, o inferno de toolchain, e até as equipes dentro do Google que mantêm cada implementação parecem não ter um consenso filosófico sobre como as funcionalidades básicas deveriam funcionar
    Tente expor uma API gRPC para uma equipe que não usa a sua linguagem — especialmente se não for Go/Python/Java, ou mesmo se usar versões antigas delas —, integrar com um produto comercial pronto, ou expor ao navegador, e tudo acaba exigindo uma camada intermediária

    • Já usei gRPC em várias empresas e equipes, com algo em torno de 100 a 500 engenheiros em cada empresa, e não tivemos problemas de dependências nem de toolchain
      gRPC foi, em geral, tranquilo
    • Acho que não se deve expor diretamente ao navegador. Esse não é o ponto forte do gRPC; é melhor criar uma camada personalizada que converta para JSON
      Usar REST para comunicação entre serviços de backend também não faz muito sentido se houver requisitos de desempenho, e há poucos motivos para usar um protocolo/API legível por humanos se não for uma chamada ocasional que recebe poucos dados
    • Lembro de tentar expor uma API gRPC ao navegador e ser cobrado por não ter criado uma interface “com cara de JSON”
      Quando retornávamos um subtipo de oneof que não tinha campos naquele momento, o resultado da conversão automática ficava algo como { "id": "id", "sub_type_two": { } }
      Funcionalmente, isso funcionava, e o código continuaria funcionando mesmo se campos fossem adicionados depois. Mas, no mundo web, representar o tipo da resposta com um objeto vazio é estranho, e esse problema pode não ficar muito evidente ao escrever protobuf
    • Streaming bidirecional costuma ser uma má ideia para algo que você pretende operar “em escala”
    • Protobuf não é adequado para streaming
      Comparado a praticamente qualquer protocolo binário imaginável, ele é quase anti-streaming
  • A única experiência que tive usando gRPC em uma empresa foi em um projeto que outro desenvolvedor sênior empurrou dizendo que “precisávamos de desempenho”
    No fim, também tivemos que criar uma API JSON porque o frontend precisava consumi-la, e ninguém além desse desenvolvedor tinha experiência com gRPC. Na prática, nem ele tinha ido além do guia de início rápido de gRPC em Python e também não ajudou a corrigir bugs
    O projeto era uma bagunça por inúmeros motivos e nunca chegou nem perto da escala que justificaria gRPC
    Ainda assim, pessoalmente gostei um pouco do gRPC que usei, e fiquei com a sensação de que ele exige muito mais trabalho e reflexão. Talvez seja só porque já fiz muito mais APIs JSON

    • Isso parece mais uma crítica ao desenvolvedor “sênior” que nem sabia, antes da adoção, que não era compatível com navegadores, do que ao gRPC em si
  • Tenho usado ConnectRPC https://connectrpc.com/ com interesse
    Ele corrige muitas das partes problemáticas do gRPC, e espero que, quando o Safari adotar WebTransport, o ConnectRPC consiga desenvolver um streaming melhor
    No começo achei que https://buf.build era exagerado, mas a capacidade de importar arquivos proto de terceiros sem baixar um por um foi decisiva
    deps:
    - buf.build/landeed/protopatch
    - buf.build/googleapis/googleapis
    A geração automática de SDKs também é importante. Antes eu ia elogiar o fato de ele gerar SDKs automaticamente para cerca de 9 linguagens, mas ele foi atualizado nos últimos um ou dois dias e agora vejo 16 linguagens, além de OpenAPI e outros recursos novos
    Eu também fui seduzido pela falsa promessa do streaming do gRPC, e este documento bateu exatamente com a minha experiência: https://connectrpc.com/docs/go/streaming/

    • Criei um pequeno wrapper baseado em WebSocket para streaming do ConnectRPC para fazê-lo funcionar no ReactNative
      Graças a isso, também é possível usar streaming bidirecional no navegador
    • Ainda assim, ele usa Protocol Buffers, e muitos dos problemas que tenho com gRPC vêm justamente daí
    • Fico curioso se há notícias recentes sobre o suporte do Safari a WebTransport
  • Parece que o Google fez uma espécie de guerra psicológica com todo o setor para obrigar todo mundo a usar gRPC na comunicação entre serviços internos
    A experiência do desenvolvedor do gRPC é consideravelmente pior que a de REST
    Você não consegue passar a alguém um comando simples para chamar um endpoint; é preciso usar ferramentas adicionais não padronizadas. Além disso, o código gerado do lado do cliente é um amontoado feio, raro de se ver em qualquer linguagem

    • Do ponto de vista de backend, discordo fortemente da afirmação de que a experiência do desenvolvedor do gRPC é pior que a de REST
      Com uma mudança de protocolo, dá para saber estaticamente quais consumidores downstream precisam ser atualizados e redistribuídos, o que pode transformar um trabalho de semanas em uma alteração de uma hora
      Você também sabe que as mensagens recebidas e enviadas são validadas imediatamente, e pode armazená-las de forma barata para reconstruí-las depois
      Com proto, você obtém uma documentação de API muito legível, sem ela ficar embaralhada com código ou lógica de negócio. Versionamento e semântica de descontinuação também vêm embutidos e, com exceção de mapas, há suporte a estruturas de dados mais ricas
      Em comparação, JSON parece inchado e antiquado no backend
    • gRPC é um padrão nos aspectos importantes
      Você escreve os tipos de dados e as assinaturas das funções e obtém algo que pode ser chamado como uma função de verdade, podendo se concentrar na lógica de negócio em vez de boilerplate de serialização/desserialização
      Thrift também é muito melhor do que fazer tudo manualmente, e acho GraphQL ainda melhor
    • Usei à força em várias empresas, mas em 99% dos casos foi um investimento em dívida técnica desnecessária
      Mesmo em Go, lidar com regeneração e gerenciamento de versões de protos compartilhados é trabalhoso, e fica pior a cada nova linguagem adicionada
      Ainda assim, parece que toda startup acha que precisa de 100 microsserviços e gRPC
  • A frase “se uma API é uma API REST, o cliente não precisa entender o formato da URL, e esse formato não faz parte da especificação da API entregue ao cliente” se conecta à definição de REST de Roy Fielding
    Fielding escreveu que uma API REST deve ser acessada sem conhecimento prévio além do URI inicial e de um conjunto de media types padronizados, e que todas as transições de estado da aplicação depois disso devem ocorrer com o cliente escolhendo entre as opções fornecidas pelo servidor
    https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...
    É um assunto já muito discutido, mas ainda acho interessante que, em um sistema verdadeiramente RESTful, a “especificação da API” entregue ao cliente deveria ser apenas o URI/URL do ponto de entrada inicial

    • A ideia de REST autodescritivo hoje é mais conhecida como HATEOAS
      Pessoalmente, acho inchada e que não resolve problemas reais
      https://en.m.wikipedia.org/wiki/HATEOAS
    • Fico curioso sobre como escrever um cliente de API para uma API REST que expõe apenas o ponto de entrada inicial
      Especialmente, não sei como o cliente deveria descobrir os recursos que pode manipular ou os modelos de requisição/resposta
    • Não concordo totalmente que, em um sistema verdadeiramente RESTful, a especificação da API entregue ao cliente deva ser apenas o URI/URL do ponto de entrada inicial
      A configuração pode ser assim, mas a especificação da API precisa conter muito mais que uma URL e deve descrever em detalhes os media types usados pelo sistema. Ou seja, a maior parte dela precisa explicar os corpos das requisições/respostas HTTP
      O link também diz que “uma API REST deve dedicar quase todo o esforço descritivo à definição dos media types usados para representar recursos e conduzir o estado da aplicação”
      No fim, não se trata apenas de retornar application/json, mas algo como um +json específico, e na maioria das vezes isso contém dados de negócio que a aplicação precisa entender, não JSON genérico
      Nas discussões populares, o foco acaba ficando só na URL inicial, e a maior parte do trabalho que Fielding menciona — “descreva os media types” — fica de fora. Por isso é natural que alguém que ouviu “basta uma URL” pergunte “onde está o resto da especificação?”
    • Os dois estão concordando com a mesma coisa. Aqui, “formato da URL” é literalmente o formato da URL, não o formato do recurso
      Eu também cliquei no texto achando que seria mais um blogueiro que não entendeu REST, mas o autor pelo menos parece conhecer os conceitos básicos
      Também gosto de gRPC e ele é bastante atraente em projetos comerciais, mas, para projetos pessoais ou idealistas, acho REST melhor
    • É um caso típico de uma boa ideia que vira moda e depois continua sendo propagada por pessoas que a entenderam errado
  • Não gosto de usar gRPC dentro de datacenters
    Ele é escolhido por desempenho, mas é difícil considerar gRPC de alto desempenho, e a qualidade dos clientes públicos também é muito baixa, especialmente fora das implementações centrais em C++/Java. A implementação em Node.js, por exemplo, é assim
    Não sou contra usar protobuf como especificação de API, mas deveria ser possível usá-lo com um protocolo de framing sobre TCP. Só que, nesse tipo de RPC, não há uma opção claramente dominante
    Em APIs baseadas na web, prefiro payloads legíveis, mas geralmente se usa JSON e a especificidade de tipos fica frouxa, o que causa problemas de interoperabilidade entre linguagens de backend. Especialmente em Node.js, JSON.parse acaba sendo usado como se fosse uma implementação de mapeamento de schema
    Para fazer isso direito, é preciso gerar explicitamente encoders e decoders a partir do schema, e aí parte da vantagem de usar JSON no contexto de JS diminui

    • Se você está considerando gRPC por preocupação com desempenho, fico curioso por que seria aceitável ter Node.js perto da sua stack ao mesmo tempo
    • Concordo, e Zod ajuda muito com o problema de schemas em JS
      Também estou acompanhando o projeto TypeSpec da Microsoft: typespec.io
    • A principal vantagem de proto é a interoperabilidade entre várias linguagens
      Se a stack tecnológica usa uma única linguagem, isso perde importância. E, se você usa algo fora das principais linguagens do Google, é bem provável que a experiência não seja tão boa
    • Em 2023 houve uma apresentação sobre Homa, um protocolo não baseado em TCP para RPC em datacenters: https://youtu.be/xQQT8YUvWg8?si=g3u5TogBe0_QpPpj
  • O gRPC parecia desnecessariamente pouco acessível para quem estava fora do Google
    O cliente gRPC em JS é desnecessariamente pesado e bastante opaco. A ideia é boa, mas a execução deixa a desejar quando comparada a pessoas acostumadas à “simplicidade” do REST

    • Na fronteira entre frontend e backend, o campo REST/JSON entra em choque com o campo RPC/protobuf/gRPC
      RPC é semanticamente mais fácil de manter porque não obriga a encaixar a cardinalidade ou as relações do modelo de dados em um único padrão prescritivo. Em um mundo em que APIs mudam rapidamente, é difícil acertar entidades RESTful bonitas; em equipes grandes e com requisitos/propriedade em mudança, um design centrado em serviços é melhor
      O lado frontend não mantém os sistemas de backend. Ele quer APIs fáceis de entender e entidades que possam ser abstraídas com REST. É o beneficiário final desse tipo de design
      O esforço exigido pelo REST faz sentido em empresas que vendem APIs e têm desenvolvedores terceiros como clientes principais
      Para desenvolvimento de backend, protobuf e codificação binária no fio são mais fáceis. É possível definir uma API e compartilhá-la entre serviços de forma estaticamente tipada, além de reduzir o tempo de codificação/decodificação de mensagens. JSON não é semântico nem tipado, e ainda tem overhead alto
      Por outro lado, o frontend lida nativamente com texto e JSON. Não quer baixar definições protobuf nem tratar dados binários como cidadãos de segunda classe, e isso também não se encaixa de forma limpa nas ferramentas
      O gRPC incorpora bem roteamento, novas tentativas, canais auxiliares, streaming e semântica de descontinuação de protocolo, mas quase nada disso fica exposto ao frontend. Tudo isso é voltado para consumidores de backend
      No fim, é 100% uma lacuna de ferramentas entre frontend e backend, e um desalinhamento entre interface e usabilidade
    • REST é parecido com HTML
      Por padrão, dá para ver o código-fonte, é legível por humanos e fácil de inspecionar
      gRPC é feito para máquinas conversarem de forma eficiente entre si; quando humanos entram no meio, seja programando ou inspecionando requisições/respostas, fica um pouco incômodo
      Como o contexto e os objetivos eram diferentes, essa diferença de usabilidade é compreensível
    • A implementação oficial de gRPC para JavaScript é meio ruim
      Na minha opinião, a implementação da buf.build é boa
      https://buf.build/blog/protobuf-es-the-protocol-buffers-type...
    • gRPC é uma boa ideia, mas ficou pesado com soluções para problemas ao estilo Google que eu não tenho
      Parece que muita gente o escolheu por precisar de um protocolo como RPC binário com contrato, mas quanto mais se afasta de GoLang, pior ele fica
    • Há usos em que o gRPC brilha. Streaming é um deles, permitindo enviar de forma transparente um fluxo de mensagens dentro de uma única “conexão”
      Para um serviço CRUD simples, REST já é suficiente