Engenharia iOS

[Arquitetura iOS #5] Por que o VIPER caiu em desuso (RIBs)

Poucos padrões de arquitetura iOS dividem tanto as opiniões quanto o VIPER.

4 min de leitura
Imagem de capa de [Arquitetura iOS #5] Por que o VIPER caiu em desuso (RIBs)

Poucos padrões de arquitetura iOS dividem tanto as opiniões quanto o VIPER.

Alguns o chamam de “resposta para a colaboração em equipes grandes”; outros, de “inferno do boilerplate”. Vários apps de serviços grandes adotaram o VIPER ou variantes e, anos depois, migraram para estruturas mais leves.

Hoje, vamos resumir o que o VIPER tentava resolver e por que o custo era tão alto.


VIPER tem cinco peças

O VIPER divide uma tela em cinco responsabilidades. O próprio nome vem das iniciais delas.

  • View: exibe a tela, incluindo o view controller. Apenas “desenha”.
  • Interactor: lógica de negócio. Busca dados e aplica regras.
  • Presenter: faz a mediação entre View e Interactor. Prepara os dados para a tela.
  • Entity: modelo de dados puro.
  • Router (Wireframe): cuida da navegação.

Ele divide em quatro partes o trabalho que um único view controller fazia no MVC (Model-View-Controller) e extrai a navegação para uma peça separada (Router). Cada responsabilidade do Massive View Controller visto na primeira parte ganha seu próprio lugar.

A regra central é uma relação de referências estrita e quase unidirecional. View conhece apenas Presenter; Presenter conhece Interactor e Router; Interactor toca apenas em Entity. Cada limite é definido por um protocolo, permitindo trocar qualquer peça por um mock.


O que melhora?

Há situações claras em que essa estrutura brilha.

Primeiro, dá para elevar a cobertura de testes ao máximo. Como todo limite é um protocolo, Interactor, Presenter e Router podem ser testados isoladamente.

Segundo, facilita a divisão de trabalho em equipes grandes. Toda tela tem a mesma estrutura, tornando previsível a organização dos arquivos. Essa uniformidade realmente ajuda quando dezenas de pessoas mexem no mesmo código.

Terceiro, combina bem com a modularização por funcionalidade. Como cada tela é um conjunto autocontido de cinco peças, é mais fácil extrair módulos por funcionalidade. O RIBs, criado pela Uber e inspirado no VIPER, leva essa ideia ao extremo: divide o app em uma árvore por unidades de lógica de negócio, não por Views.

Até uma tela com um único botão é forçada a ter as mesmas cinco peças.
Até uma tela com um único botão é forçada a ter as mesmas cinco peças.

Então por que todo mundo abandonou?

O problema é o custo.

O boilerplate é enorme. Mesmo uma tela com um botão gera seis ou sete arquivos: View, Interactor, Presenter, Entity, Router e os protocolos entre eles. A reclamação de que “para mudar o texto de um label é preciso passar por três arquivos” não é exagero.

Até telas simples são obrigadas a carregar o mesmo peso. Uma tela estática de configurações e uma tela complexa de feed recebem cinco peças. O peso da estrutura não acompanha a complexidade da tela.

A curva de aprendizado e o custo de onboarding também são consideráveis. Quem vê pela primeira vez o caminho dos dados — View → Presenter → Interactor → Presenter → View — precisa de tempo para acompanhá-lo.

O golpe final foi a chegada do SwiftUI. O VIPER surgiu de uma preocupação da era UIKit: retirar responsabilidades dos view controllers. No SwiftUI, View já é leve e a navegação funciona de outra forma, tornando peças como Router estranhas. O problema de base mudou.


Então o VIPER fracassou?

É difícil dizer isso. O legado do VIPER está incorporado às práticas padrão atuais.

  • Extrair a navegação para um objeto dedicado → consolidado como padrão Coordinator
  • Separar a lógica de negócio da apresentação → consolidado como camadas UseCase/Repository
  • Definir limites com protocolos → consolidado como injeção de dependência e práticas de teste

Menos equipes usam as cinco peças do VIPER juntas, mas os problemas que cada peça resolvia e suas soluções sobreviveram. Hoje, a prática se aproxima mais de escolher apenas as peças necessárias.

O padrão completo ficou para trás, mas suas peças úteis permaneceram como práticas padrão.
O padrão completo ficou para trás, mas suas peças úteis permaneceram como práticas padrão.

Resumo

  • O VIPER divide uma tela em cinco peças — View, Interactor, Presenter, Entity e Router — e define seus limites por meio de protocolos.
  • A testabilidade e a uniformidade em equipes grandes são vantagens, mas o custo de boilerplate é alto: seis ou sete arquivos por tela.
  • Com a mudança do problema de base na era do SwiftUI, menos equipes usam o VIPER em sua forma original.
  • Seu legado sobrevive em práticas padrão como Router→Coordinator e Interactor→UseCase.

No próximo artigo, vamos abordar a forma mais difundida desse legado: o que UseCase e Repository da arquitetura limpa realmente fazem no iOS.

Leituras recomendadas