Enable javascript in your browser for better experience. Need to know to enable it?

Ӱֱ

Ingeniería inversa tipo “caja negra”

¿Puede la IA ayudar a reconstruir una aplicación sin acceder a su código?

Es el tipo de escenario que pone los pelos de punta a cualquier CTO: una aplicación crítica para el negocio está funcionando, pero el código fuente ha desaparecido. Tal vez la relación con un proveedor se quebró, y ahora solo tienes un binario funcional pero opaco. O tal vez sí tienes acceso al código fuente, pero está tan desordenado que ni las personas ni la IA pueden entenderlo o describir qué hace realmente.

Una de nuestras formas habituales de acelerar la modernización de sistemas heredados con IA es empezar usando IA para facilitar la ingeniería inversa: se alimenta con el código existente y luego se usa para generar una descripción funcional completa de la aplicación, que después puede servir como base para su reconstrucción.

Pero… ¿qué pasa si no tenemos el código? ¿O si es tan caótico que no sirve? ¿Cómo puede la IA generativa acelerar la ingeniería inversa en estos casos?

En Ӱֱ nos propusimos explorar esta pregunta a través de un experimento de ingeniería inversa tipo “caja negra”. Queríamos averiguar si, combinando navegación con IA y técnicas de captura de datos, podíamos generar una especificación funcional rica de un sistema heredado y usarla para construir una versión moderna desde cero.

Esta es la historia de cómo lo hicimos, los retos que enfrentamos y las valiosas lecciones que aprendimos sobre el futuro de la modernización de sistemas heredados.

Las distintas fuentes de información para la IA en el experimento

Cómo configuramos el experimento de IA

Elegimos como sujeto de prueba a Odoo, una plataforma ERP de código abierto fácil de instalar y ejecutar localmente. El código backend de la aplicación estaba completamente fuera del alcance de la IA: solo usamos información observable desde el exterior:

  • Interfaz de usuario: La IA podía ver e interactuar con la aplicación como lo haría una persona, observando elementos estáticos, comportamiento dinámico y rutas de clics.
  • Base de datos: Aunque no accedimos al código backend, sí trabajamos con el esquema y los datos existentes.
  • Tráfico de red: También permitimos que la IA inspeccionara las peticiones de red enviadas desde el navegador hacia el servidor como fuente adicional de datos.

Alcance del experimento:

  1. Aplicar ingeniería inversa sobre un flujo central: crear una nueva oportunidad en el CRM de Odoo. El entregable fue un documento de especificación que describía el comportamiento observable de la aplicación, incluyendo capturas de pantalla.
  2. Explorar las posibilidades que ofrece la IA generativa para construir un “test de paridad funcional” que pueda ejecutarse tanto en la aplicación original como en su versión reconstruida.

Iteración uno del experimento: reconocimiento

Nuestra primera aproximación fue una exploración amplia.

  1. La IA como usuaria. Enviamos un agente de IA con acceso al servidor Playwright MCP para que navegara por la aplicación. El prompt le pedía “descubrir el recorrido del usuario para crear una nueva oportunidad en el pipeline de ventas”. El agente hizo clics a través de la interfaz, tomó capturas de pantalla y generó una descripción de todos los diálogos con sus campos y los comportamientos dinámicos que podía observar (por ejemplo: “cuando se selecciona una entrada en este menú desplegable, los campos del formulario se completan automáticamente”). También le pedimos un diagrama de flujo que describiera la secuencia de clics que encontró. El flujo resultante era un "camino feliz" muy lineal —casi sospechosamente simple—. Ninguna aplicación real es tan directa; sabíamos que había más por descubrir para que la IA identificara la complejidad real de los recorridos.
  2. Captura de cambios en los datos. Una vez que obtuvimos una primera descripción de los recorridos, pedimos a la IA que volviera a navegar por la aplicación y rastreara los cambios en la base de datos después de cada clic. Esto fue posible gracias a la configuración de triggers en la base de datos que registraban todas las operaciones de INSERT y UPDATE en una de las tablas relevantes. Construimos un pequeño servidor MCP personalizado que permitía al agente de IA consultar este registro de auditoría tras cada interacción. Como resultado, nuestra especificación funcional se enriqueció con las operaciones en la base de datos que se producían tras cada paso. Este enfoque de captura de cambios en los datos (CDC, por sus siglas en inglés) resultó ser una forma poderosa y de bajo esfuerzo para descomponer las consultas desde el exterior.
La siguiente iteración del experimento con IA: desarrollar la especificación

Iteración dos del experimento: desarrollo de la especificación

Con los aprendizajes obtenidos en nuestra primera prueba, mejoramos tanto el flujo de trabajo como los prompts. Primero, afinamos el prompt para descubrir los recorridos de clics, pidiéndole de forma más explícita que identificara y recorriera todas las acciones posibles del usuario en cada pantalla. Y en lugar de ejecutarlo una sola vez, corrimos el agente varias veces, ya que sospechábamos que la IA podría tener dificultades para detectar todas las ramificaciones del recorrido en una sola pasada. Estábamos en lo cierto: cada ejecución reveló ramas y variaciones ligeramente distintas.

Luego, usamos otro paso con IA para "converger" estas distintas versiones, analizar y verificar las discrepancias, y crear un único mapa consolidado del flujo de usuario. Los diagramas resultantes representaban mucho mejor el comportamiento real de la aplicación.

En esta iteración, también intentamos añadir una capa adicional de recolección de datos capturando el tráfico de red. La idea era hacer ingeniería inversa de la API del backend analizando los payloads JSON que se intercambian entre el frontend y el backend.

Aunque finalmente logramos generar un documento Swagger de la API, esta configuración resultó mucho más difícil de implementar que la captura de datos de cambios.

También concluimos que, para este escenario específico —donde la API es un detalle de implementación interna y no un contrato público— la información sobre la API del backend realmente no aportaba nada nuevo que no supiéramos ya sobre las estructuras de datos.

Validación a través de la reconstrucción

La prueba definitiva fue usar los artefactos generados por la IA para crear una nueva aplicación. Nuestro foco en este experimento no era la ingeniería hacia adelante, por lo que no queríamos dedicar demasiado tiempo a este paso.

Sin embargo, aún necesitábamos comprobar si la especificación era útil; así que decidimos introducirla en una de las herramientas de generación rápida de aplicaciones con IA.

Primero introdujimos nuestra especificación detallada —una colección de archivos Markdown, capturas de pantalla y descripciones de lógica de base de datos— en una serie de prompts que generaron épicas, historias de usuario y un orden de implementación. Luego, cargamos el primer conjunto de historias en Replit.

Algunas observaciones de esta fase de validación:

  • Prototipado como validador. Ver a la IA construir el prototipo fue una forma muy efectiva de validar y mejorar la especificación. Cuando el prototipo se desviaba del original, a veces era más fácil detectar un error o ambigüedad en el documento de requisitos que leyéndolo directamente.
  • La IA tiene dificultades para planificar. Los modelos de lenguaje suelen tener problemas para crear un plan de implementación lógico e incremental; y ese fue el caso aquí. Su primer impulso fue construir toda la vista del pipeline complejo de una sola vez, en lugar de comenzar con los elementos más simples e ir construyendo sobre ellos. Un buen flujo de trabajo con IA y supervisión humana son claves para guiar la estrategia de desarrollo en un entorno real.
  • Sin demostración de fidelidad en las consultas. Lamentablemente, en este caso Replit ignoró nuestras entradas sobre el esquema de la base de datos y las consultas exactas que queríamos ejecutar. Como no queríamos dedicar mucho tiempo a la ingeniería hacia adelante, esto significó que no pudimos demostrar por completo que la nueva aplicación podía conectarse a la base de datos existente. Sin embargo, la IA generativa suele ser bastante buena al captar ejemplos específicos y esquemas para usarlos en el código; no sería descabellado pensar que un agente de codificación, con indicaciones precisas, podría reproducir las consultas que recopilamos.
Usando IA para validar paridad funcional

¿Puede la IA ayudarnos a probar paridad entre aplicaciones?

Aunque la aplicación generada no era perfecta, nos brindó la oportunidad de realizar un segundo experimento: ¿cómo podríamos crear una suite de pruebas automatizadas que funcionara tanto con la aplicación original como con nuestro nuevo prototipo —ligeramente diferente—?

El reto es que, si bien esperamos los mismos controles generales para las personas usuarias, la nueva aplicación podría tener un diseño algo distinto y, sin duda, selectores diferentes en el DOM. Aquí es donde la IA ofrece ventajas: permite dar instrucciones de prueba más vagas, lo cual resulta útil en este caso. Puede utilizar información visual y responder a descripciones menos precisas de los elementos de la interfaz. Por ejemplo, podrías decir algo como “busca un ícono de +”, y podría funcionar sin importar si ese ícono está implementado como imagen o como texto.

Usamos un framework que permite añadir instrucciones de prueba en lenguaje natural a un test de Playwright. En lugar de escribir un selector como find('button#id-123'), pudimos usar instrucciones como await ai('Haz clic en el ícono + para crear una nueva oportunidad'). De esta manera, la prueba no dependía de una estructura específica del DOM, lo que permitía que fuera lo suficientemente abstracta como para ejecutarse en dos implementaciones distintas de la misma interfaz.

Al construir una suite de pruebas que se ejecutara sobre ambas aplicaciones, nos encontramos principalmente con los problemas habituales de las pruebas de extremo a extremo en navegador, como la necesidad de agregar tiempos de espera. Al sumar la no determinación de la IA sobre la ya conocida inestabilidad de este tipo de pruebas, emergieron nuevos desafíos. Es un caso de uso prometedor, pero requiere una implementación cuidadosa para evitar más ruido que señal.

Requisitos previos y limitaciones

Este enfoque depende de contar con un entorno seguro y aislado de pruebas, donde los agentes de IA puedan explorar libremente y los scripts de captura de datos se puedan ejecutar sin afectar entornos en producción.

Dependiendo del tipo y la complejidad de la aplicación, es esperable que el documento de especificaciones generado mediante ingeniería inversa contenga ciertos vacíos que deberán ser completados por personas expertas en el dominio, especialmente si hay lógica compleja que no puede observarse directamente desde la interfaz de usuario. Tampoco exploramos técnicas para escenarios con comunicación entre servicios o efectos secundarios en el backend. Una mayor captura de datos de red podría ser útil en esos casos.

Conclusiones y aprendizajes clave

Nuestro experimento demostró que hay un gran potencial en el uso de la inteligencia artificial para aplicar ingeniería inversa a una aplicación sin necesidad de acceder a su código fuente.

Aquí te compartimos tres aprendizajes principales:

  1. La IA es un acelerador, no un reemplazo. Una constante en todos nuestros experimentos es que, aunque la IA actúa como un multiplicador de capacidades, no sustituye la experiencia humana. La IA puede hacer una primera pasada, generar documentación base y liberar a las personas expertas para que se enfoquen en refinar y validar. Es un proceso de colaboración entre humanos e inteligencia artificial.
  2. Iterar y descomponer. Dividir la aplicación en recorridos de usuario y la ingeniería inversa en pasos pequeños e iterativos (descubrir, converger, agregar detalles) ayuda a obtener resultados más precisos y de mayor fidelidad.
  3. Validar de forma continua. Usar técnicas como el prototipado rápido y las pruebas de paridad permite establecer ciclos tempranos de retroalimentación.

Aviso legal: Las declaraciones y opiniones expresadas en este artículo son las del autor/a o autores y no reflejan necesariamente las posiciones de Ӱֱ.

Ayudamos a los equipos de ingeniería a acelerar con IA