Ingeniería iOS

[Arquitectura iOS #10] RIBs de Uber: dividir la app por lógica de negocio

RIBs divide una app por unidades de lógica de negocio, no por pantallas. Aquí se explican los componentes sin pantalla, por qué se usa en organizaciones muy grandes y en qué se diferencia de VIPER.

4 min de lectura
Imagen de portada de [Arquitectura iOS #10] RIBs de Uber: dividir la app por lógica de negocio

En la entrega sobre VIPER (View·Interactor·Presenter·Entity·Router) mencioné brevemente «RIBs, creado por Uber e inspirado en VIPER». En esta entrega lo veremos en profundidad. En Corea también es conocido como la arquitectura adoptada por Toss.

La clave para entender RIBs es una sola. Todas las arquitecturas tratadas hasta ahora (MVC·MVVM·VIPER·ReactorKit) usaban las pantallas como unidad básica. RIBs abandona esa premisa y divide la app por lógica de negocio, no por pantallas.


La existencia de componentes sin pantalla

RIBs es el acrónimo de Router·Interactor·Builder. Estos tres son obligatorios en cada componente (RIB); Presenter y View se añaden solo cuando hacen falta.

  • Interactor: El núcleo de la lógica de negocio, el cerebro del RIB.
  • Router: Gestiona el árbol conectando y desconectando RIBs hijos.
  • Builder: Ensambla un RIB e inyecta sus dependencias.
  • Presenter·View: Opcionales. Solo existen en los RIB que necesitan una pantalla.

Que «View sea opcional» es decisivo. Pensemos en el estado «en viaje» de una app de transporte. Abarca el mapa, la tarjeta con los datos del conductor y la lógica de preparación del pago, pero no es una pantalla concreta. En RIBs se convierte en un RIB sin pantalla, viewless, con RIBs hijos que sí tienen pantalla conectados debajo.

Toda la app se convierte en un árbol de RIBs. Los cambios de estado de la app, como el inicio de sesión o el estado del viaje, son cambios en la forma del árbol. Al cerrar sesión, el RIB LoggedIn se desprende por completo del árbol, junto con sus pantallas y lógica. Gestionar el estado equivale a gestionar el árbol.

Diagrama de la estructura en árbol de RIBs y de la diferencia entre RIBs sin pantalla y RIBs con View
Los estados de la app, como el inicio de sesión y el viaje, definen la forma del árbol

¿Por qué solo lo usan las organizaciones muy grandes?

RIBs se diseñó desde el principio para «cuando cientos de personas crean una sola app». Decenas de equipos incorporan código simultáneamente en la app de Uber, y dividir por pantallas no bastaba para crear límites entre equipos: la lógica de varios equipos se mezclaba en una misma pantalla.

Al dividir por RIB, cada equipo posee su propio subárbol de RIBs. Como Builder fuerza los puntos de inyección de dependencias, ni siquiera se puede acceder al interior del RIB de otro equipo. Es la «imposición de límites» de la serie sobre modularización aplicada a nivel de arquitectura.

Toss adoptó RIBs por el mismo motivo. En una superapp con decenas de servicios financieros, convertir cada servicio en un subárbol de RIBs hace explícito cuándo conectarlo y desconectarlo.

Por el contrario, todas estas ventajas se convierten en costes para un equipo pequeño.

Primero, RIBs tiene más boilerplate que VIPER. Un RIB suele generar cuatro o cinco archivos. Por eso Uber también ofrece plantillas de generación de código.

Segundo, la curva de aprendizaje es pronunciada. El equipo debe aprender el diseño del árbol, los momentos de attach/detach y la inyección de dependencias por ámbito para compartir el mismo modelo mental.

Tercero, choca con el pensamiento centrado en pantallas. Las especificaciones suelen definirse por pantalla, pero RIBs divide por estado, así que hay que traducir entre ambos durante el diseño.

¿En qué se diferencia de VIPER?

Por los nombres de sus componentes parece una variante de VIPER, pero la diferencia es fundamental.

VIPER RIBs
Unidad básica Pantalla Lógica de negocio
Componente sin pantalla Imposible viewless RIB
Navegación El Router cambia de pantalla El Router conecta y desconecta el árbol
Objetivo Separar las responsabilidades de una pantalla Separar la propiedad del código por unidad organizativa

El Router de VIPER responde a «¿cómo pasamos a la siguiente pantalla?», mientras que el Router de RIBs responde a «¿qué componentes de lógica deben estar activos en el estado actual de la app?». El mismo nombre, una pregunta distinta.

Ilustración de la propiedad del código por equipo en RIBs, dividida en subárboles TEAM A, B y C
El verdadero objetivo de RIBs es que cada equipo posea su propio subárbol

Resumen

  • RIBs es la arquitectura de Uber para dividir una app en un árbol de unidades de lógica de negocio, no de pantallas.
  • Permite RIBs sin pantalla y representa los cambios de estado de la app mediante attach/detach en el árbol.
  • Su objetivo es separar la propiedad del código por equipo e imponer límites, por lo que destaca en organizaciones de cientos de personas. Uber y Toss son casos representativos.
  • En equipos pequeños, el boilerplate y la curva de aprendizaje superan las ventajas. Como se explicó en la guía de selección de la entrega 8, el tamaño del equipo es el factor principal.

Con esto completamos las piezas de la serie de arquitectura iOS que solo habíamos mencionado. De MVC a RIBs, todas las arquitecturas son respuestas distintas a la misma pregunta: «¿Dónde debe ubicarse la lógica?»

Seguir leyendo

Serie de arquitectura iOS