Uber publicó un informe sobre cómo migraron 75,000+ clases de pruebas y 1.25 millones de líneas de código de pruebas a través de su monorepo Java de JUnit 4 a JUnit 5, y el detalle principal para cualquier equipo que actualmente esté sopesando refactoring asistido por IA es que Uber eligió explícitamente no usar IA generativa para la transformación. Su razonamiento declarado, citado en el informe: «El herramental de transformación determinista era crítico para la consistencia a esta escala», y los enfoques basados en LLM «producían resultados inconsistentes en patrones de pruebas personalizados». En su lugar, el equipo construyó sobre OpenRewrite, el framework open-source de transformación semántica de código que opera sobre árboles semánticos sin pérdida en lugar de texto crudo, con recetas personalizadas que apuntan a clases base y ejecutores de pruebas específicos de Uber. Lo emparejaron con una capa de compatibilidad de ejecución unificada (JUnit Platform corriendo Vintage y Jupiter simultáneamente, para que los repos parcialmente migrados siguieran funcionando), verificaciones de precondición para bloquear migraciones parciales, y un sistema de orquestación interno llamado Shepherd que distribuyó transformaciones a través de miles de objetivos Bazel en paralelo y validó cada uno vía CI.
La realidad técnica detrás de la elección es más interesante de lo que sugiere el encuadre LLM-versus-no-LLM. A escala Uber, el modo de fallo que más importa es la inconsistencia silenciosa: una transformación que funciona en el 99.5% de los archivos y silenciosamente destroza el 0.5% crea 375 clases de pruebas rotas, cada una de las cuales tiene que ser diagnosticada y corregida a mano. Las recetas OpenRewrite son deterministas; dado el mismo AST de entrada y la misma receta, obtienes la misma salida cada ejecución, y las transformaciones son expresables como visitantes componibles sobre un árbol semántico tipado. La transformación de código basada en LLM, en contraste, es no-determinista a nivel de token y especialmente lucha con patrones raros que no ha visto a menudo en los datos de entrenamiento, que es exactamente donde viven los ejecutores de pruebas personalizados y las jerarquías de clases base de Uber. El artículo de InfoQ nota que las ejecuciones iniciales de Shepherd hicieron emerger fallos de build y de pruebas que informaron actualizaciones a la lógica de transformación; este es el bucle de iteración que realmente puedes correr con herramental determinista porque los fallos son reproducibles. Con un LLM, vuelves a correr el mismo prompt y obtienes un error ligeramente diferente, lo que es mucho más difícil de diagnosticar a escala.
La implicación más amplia para la narrativa de herramientas de codificación con IA vale la pena ser preciso. Uber no está diciendo que los LLM no puedan hacer transformación de código; están diciendo que para esta clase específica de problema (alto volumen, mecánico-pero-rico-en-patrones, crítico para la corrección), el herramental determinista ganó. Esto coincide con lo que los laboratorios de frontera mismos hacen internamente: las reescrituras de bases de código a gran escala en Google, Meta, y Microsoft han sido por años hechas con herramientas de refactoring deterministas (motores de reescritura, jscodeshift, transformaciones estilo gofmt, Comby, OpenRewrite), con LLM usados selectivamente para la cola larga de patrones que las recetas deterministas no pueden expresar. El encuadre en la prensa tech de «la IA reemplaza el refactoring de código» tiene esto al revés: a escala el asistente de IA está en la escritura de recetas y manejo de casos límite, no en la pasada de transformación masiva. La economía también favorece el determinismo para una migración única: escribir una receta es un costo fijo que se amortiza a través de 75,000 archivos, mientras que correr un LLM sobre 75,000 archivos es un costo variable que escala linealmente y produce salida que aún tienes que verificar.
Para equipos constructores, la conclusión accionable es pensar en tus tareas de refactoring en tres cubos. Primero, transformaciones mecánicas de patrones con reglas finitas bien definidas: renombrar API, actualizar imports, intercambio de anotaciones, migración de versión JUnit. Esto pertenece a herramientas AST deterministas, punto, y el informe de Uber es el caso de estudio reciente más claro de cómo se ve eso a escala. Segundo, refactorings semánticos con llamadas de juicio: extraer una abstracción, renombrar para claridad, reestructurar flujo de control. Aquí es donde las herramientas de codificación asistida por IA ganan su sustento, porque las ediciones son locales, revisables, y la flexibilidad del LLM ayuda donde las recetas rígidas se rompen. Tercero, trabajo de corrección de bugs o características con refactoring incrustado: este es el punto dulce de las herramientas de codificación agéntica, donde el modelo puede leer el contexto circundante y adaptarse. El error a evitar es usar una herramienta de un cubo para un trabajo de otro. La elección de Uber de enviar 1.25M líneas de migración mecánica en OpenRewrite, con un bucle CI determinista y orquestación paralela, es la respuesta correcta para el cubo uno, y vale la pena tenerla en mente la próxima vez que alguien proponga lanzar Claude o GPT a un refactor de un millón de líneas.
