No artigo sobre VIPER (View·Interactor·Presenter·Entity·Router), mencionei rapidamente “RIBs, criado pela Uber e inspirado em VIPER”. Nesta edição, vamos tratar do assunto de verdade. No Brasil, também é conhecido como a arquitetura adotada pela Toss.
Há uma única chave para entender RIBs. Todas as arquiteturas abordadas até agora (MVC·MVVM·VIPER·ReactorKit) usavam as telas como unidade básica. RIBs abandona essa premissa e divide o app por lógica de negócio, não por telas.
A existência de componentes sem tela
RIBs é a sigla de Router·Interactor·Builder. Esses três são obrigatórios em cada componente (RIB); Presenter e View só são adicionados quando necessário.
- Interactor: O núcleo da lógica de negócio, o cérebro do RIB.
- Router: Gerencia a árvore fazendo attach e detach de RIBs filhos.
- Builder: Monta um RIB e injeta suas dependências.
- Presenter·View: Opcionais. Existem apenas em RIBs que precisam de uma tela.
O fato de “View ser opcional” é decisivo. Pense no estado “em corrida” de um app de transporte. Ele abrange o mapa, o cartão com os dados do motorista e a lógica de preparação do pagamento, mas não é uma única tela. No RIBs, ele vira um RIB sem tela, viewless, com RIBs filhos que têm telas conectados abaixo dele.
O app inteiro se torna uma árvore de RIBs. As mudanças de estado do app, como login e status da corrida, são mudanças no formato da árvore. Ao sair da conta, o RIB LoggedIn é removido por completo da árvore, junto com suas telas e lógica. Gerenciar estado é, na prática, gerenciar a árvore.
Por que apenas organizações muito grandes usam isso?
RIBs foi projetado desde o início para “quando centenas de pessoas criam um único app”. Dezenas de equipes adicionam código simultaneamente ao app da Uber, e a separação por tela não conseguia criar limites entre equipes: a lógica de várias equipes se misturava em uma só tela.
Ao dividir por RIB, cada equipe passa a ser dona do próprio subtree de RIBs. Como o Builder força os pontos de injeção de dependência, não há como tocar no interior do RIB de outra equipe. É a “imposição de limites” da série sobre modularização realizada no nível da arquitetura.
A Toss adotou RIBs pelo mesmo motivo. Em uma superapp com dezenas de serviços financeiros, transformar cada serviço em um subtree de RIBs deixa claro quando anexá-lo e removê-lo.
Por outro lado, todas essas vantagens se tornam custos para equipes pequenas.
Primeiro, RIBs tem mais boilerplate que VIPER. Um RIB normalmente gera quatro ou cinco arquivos. Por isso, a Uber também fornece templates de geração de código.
Segundo, a curva de aprendizado é íngreme. É preciso aprender o design da árvore, os momentos de attach/detach e a injeção de dependência por escopo para toda a equipe compartilhar o mesmo modelo mental.
Terceiro, isso entra em conflito com o pensamento centrado em telas. Especificações normalmente são feitas por tela, enquanto RIBs divide por estado, então é necessário traduzir entre os dois na fase de design.
Qual é a diferença em relação ao VIPER?
Pelos nomes dos componentes, parece uma variação do VIPER, mas a diferença é fundamental.
| VIPER | RIBs | |
|---|---|---|
| Unidade básica | Tela | Lógica de negócio |
| Componente sem tela | Impossível | viewless RIB |
| Navegação | Router faz a transição de tela | Router faz attach/detach da árvore |
| Objetivo | Separar as responsabilidades de uma tela | Separar a propriedade do código por unidade organizacional |
O Router do VIPER cuida de “como ir para a próxima tela”, enquanto o Router do RIBs cuida de “quais componentes de lógica devem estar ativos no estado atual do app”. Mesmo nome, pergunta diferente.
Resumo
- RIBs é a arquitetura da Uber para dividir um app em uma árvore de unidades de lógica de negócio, não de telas.
- RIBs sem tela são permitidos, e as mudanças de estado do app são expressas como attach/detach na árvore.
- O objetivo é separar a propriedade do código por equipe e impor limites, por isso RIBs se destaca em organizações com centenas de pessoas. Uber e Toss são exemplos representativos.
- Para equipes pequenas, boilerplate e curva de aprendizado superam os benefícios. Como explicado no guia de escolha da edição 8, o tamanho da equipe é o principal fator.
Com isso, completamos as partes da série de arquitetura iOS que haviam sido apenas mencionadas. De MVC a RIBs, todas as arquiteturas são respostas diferentes à mesma pergunta: “Onde a lógica deve ficar?”
Continue lendo
Série de arquitetura iOS
- Artigo anterior: [Arquitetura iOS #9] Resumo do ReactorKit: o padrão da arquitetura unidirecional
- Artigo anterior: [Arquitetura iOS #8] Guia para escolher uma arquitetura iOS: tamanho da equipe, vida útil do app e complexidade do estado
- Artigo anterior: [Arquitetura iOS #7] Introdução ao TCA (The Composable Architecture): resumo completo do fluxo de dados unidirecional

![Imagem de capa de [Arquitetura iOS #10] RIBs da Uber: dividindo o app pela lógica de negócio](/assets/images/posts/f06929f4-621d-40e7-88d9-8817b02ef56d/uber-ribs-architecture-hero-1.jpg)