Wednesday, October 1, 2025

Saliendo del infierno de dependencias con el algoritmo de Tarjan

Kenny
Kenny

Supongamos lo siguiente: llevas un tiempo construyendo una app, con cientos de archivos, módulos, clases, etc. De repente, te das cuenta de que el proyecto está entrando en terreno peligroso: el módulo Users necesita el módulo Auth para funcionar, pero sorpresa, el módulo Auth también necesita el módulo Users. Es como dos personas intentando pasar por una puerta giratoria al mismo tiempo, una entrando y otra saliendo... estamos en problemas, amigo.

Las dependencias estaban rompiendo nuestro código

El problema que teníamos

Como en cualquier equipo de desarrollo, en Volt trabajamos en algo bastante complejo, y mantener todo bien organizado, en módulos bien definidos, es clave.

Pero la realidad siempre es distinta a lo que esperas: al depender de todo el núcleo de WhatsApp, aparecían decenas de race conditions que hacían que todo se rompiera al azar…

Tomamos el camino fácil:

  • Timeouts esperando que los módulos cargaran en menos de 750 ms
  • Loops infinitos que revisaban si un módulo interno de WhatsApp existía antes de ejecutar nuestro código
  • Lógica de reintentos dudosa que, por arte de magia, hacía que todo funcionara

Era un desastre: poco claro, poco confiable y… entre nosotros, bastante vergonzoso. Los chicos y yo pasamos demasiado tiempo peleando con estos problemas de dependencias.

El descubrimiento de Mati

Un día, las cosas se pusieron interesantes. Mati pasó horas investigando el código minificado de WhatsApp y descubrió algo que nos habría ahorrado incontables horas y dolores de cabeza.

WhatsApp había encontrado una forma muy elegante de manejar las dependencias circulares y las interdependencias, tratándolas como grupos interconectados: el maravilloso algoritmo de Tarjan, un algoritmo que permite identificar componentes fuertemente conectados en un grafo dirigido. Internamente, con este algoritmo, WhatsApp podía cargar los módulos en el orden necesario, incluso de forma parcial cuando hacía falta, asegurando que todos los módulos relacionados quedaran cargados. Una verdadera obra de arte de ingeniería.

GIF

Algoritmo de Tarjan

Es como analizar un grupo de amigos donde todos se conocen (algunos más, otros menos). ¡¡¡Este algoritmo se encargaba de encontrar esos grupos y manejarlos de forma especial según hiciera falta!!!

Cómo trabajamos con esto

Esta es la mejor parte: no construimos nuestro propio sistema de manejo de dependencias, ni seguimos usando esas técnicas dudosas para que las cosas funcionaran. Como prácticamente trabajamos dentro del código de WhatsApp, solo tuvimos que usar su solución: victoria fácil.

Ahora, cada módulo que construimos es una belleza, y WhatsApp se encarga de la parte complicada:

  • Detecta cuándo un módulo depende de otro (incluso en círculos)
  • Se asegura de que cada módulo encuentre los otros que necesita
  • Todo se carga en el orden correcto, sin trucos

De verdad, es como tener un asistente que se ocupa de todos los dolores de cabeza que nos traían las dependencias, sin timeouts y sin loops.

Por qué esto le cambió todo al equipo

Gracias a todo esto, construir módulos nuevos no cuesta nada: usamos el mismo sistema de inyección de dependencias que usa el propio equipo de WhatsApp para sus funciones, y dejamos de pelear con esta arquitectura para empezar a extenderla y sacarle el máximo provecho.

Nuestro código ahora es:

  • Más limpio y más lógico
  • Mucho más fácil de mantener para el equipo
  • Hasta divertido de trabajar

Gracias al descubrimiento de Mati, en Volt literalmente usamos la solución de WhatsApp (probada en batalla) para combatir el infierno de dependencias.

La lección más grande

A veces, las mejores soluciones no vienen de reinventar la rueda de una forma más sofisticada, sino de entender lo que ya funciona y construir encima. WhatsApp ya había resuelto, con pura matemática, el problema que nos atormentó durante tanto tiempo. Toma este post como un recordatorio de que la ingeniería más elegante muchas veces viene de dar unos pasos atrás, entender lo que ya existe y descubrir cómo aprovecharlo.

Y también de que, a veces, los mejores descubrimientos vienen de un compañero lo bastante valiente como para meterse días en código minificado, solo para concluir al final que… lo que nos hacía sangrar estuvo frente a nosotros todo el tiempo.