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

¿Puede la IA ayudar a modernizar código C++ legacy en automoción?

A medida que los vehículos definidos por software (SDVs) han ganado protagonismo en el mercado automotriz, la industria se ha visto obligada a replantear su enfoque de arquitectura. Estamos empezando a ver un cambio del diseño eléctrico basado en muchas unidades de control electrónico distribuidas (ECU) hacia lo que se conoce como arquitectura zonal.

 

Este cambio trae consigo muchos beneficios: un mejor flujo de datos, mayor eficiencia en las actualizaciones de software y funcionalidades over-the-air (OTA), por mencionar algunos. Sin embargo, también exige una modernización significativa de las bases de código. Esto resulta especialmente complejo porque gran parte del software que corre en los vehículos está escrito en C++, un lenguaje notoriamente difícil de leer.

 

Ese no es el único reto. Modernizar C++ en este contexto no significa solo refactorizar u optimizar código existente; también es necesario integrarlo con nuevas capas de software para garantizar la compatibilidad con hardware moderno y protocolos de comunicación asincrónicos, como CAN o SOME/IP.

 

Hacer esto bien es crucial para la industria automotriz. En este artículo exploro cómo las herramientas de IA generativa podrían ayudarnos a modernizar rápidamente el complejo código en C++. Estas herramientas pueden ser determinantes para que los fabricantes de automóviles aprovechen todo el potencial del SDV con rapidez y se mantengan competitivos en un entorno en constante evolución.

 

Modernización de C++ con una herramienta de IA

 

En Thoughtworks hemos desarrollado una herramienta de IA generativa específicamente diseñada para ayudar a los equipos a modernizar código legacy: CodeConcise. CodeConcise fue creada inicialmente para acelerar la ingeniería inversa de grandes bases de código en COBOL. Sin embargo, es extensible y puede adaptarse a muchos otros lenguajes de programación, incluido C++. Queríamos explorar cómo usar CodeConcise en el contexto automotriz y de SDVs con la esperanza de simplificar y acelerar el proceso de modernización. Comenzamos nuestras pruebas con Autoware Universe, un software stack open source para vehículos autónomos desarrollado por la Autoware Foundation, construido sobre el Robot Operating System 2 (ROS 2).

 

Cómo funciona CodeConcise

 

Antes de profundizar, vale la pena explicar cómo funciona realmente CodeConcise. Consta de dos partes: el análisis del código que se le proporciona y la interfaz de usuario que incluye, entre otras cosas, un chat. Para poder interactuar con la base de código mediante un chatbot o ver las capacidades extraídas por el LLM, primero debemos hacer que la herramienta conozca nuestra base de código específica.

 

CodeConcise utiliza RAG respaldado por un knowledge graph que se inserta en una base de datos Neo4j. Esta ingesta es la primera fase: el código se inserta en el grafo de forma estructurada, para que en una segunda fase el LLM pueda entender las distintas partes de la base de código y cómo encajan entre sí.

 

Observamos que otras integraciones de lenguajes usaban análisis de código estático para extraer e ingerir fragmentos. Empezamos dividiendo el código en clases, después en métodos, y luego extrayendo namespaces. Finalmente, dejamos atrás el análisis estático y pasamos a CLANG (usando los bindings de Python de LLVM libclang), un frontend de compilador. Esto ayudó a manejar la complejidad de C++ y nos permitió implementar distintas relaciones entre fragmentos lógicos del código.

 

Al hacerlo, no solo analizábamos el código; también podíamos usar el árbol de sintaxis e insertar partes de este en el grafo.

Dividir nuestra base de código C++ en fragmentos dentro de la base de datos grafo se usa después en la segunda fase de análisis, que describimos como comprensión.

Aquí la herramienta recorre los fragmentos y usa un LLM para resumir cada uno, insertando un embedding en la base de datos. También se extrajeron capacidades de negocio de nuestra base de código en esta etapa.

 

En la fase de ingesta intentamos crear un contexto comprensible para el LLM; en la fase de comprensión usamos IA para añadir detalles personalizables al knowledge graph. Tras completar la ingesta y la comprensión de los fragmentos básicos y sus relaciones, finalmente pudimos usar la interfaz de chat para profundizar en la base de código y hacer preguntas sobre ella.

 

Esto ya era bastante útil: al ingerir fragmentos de código, podíamos aprovechar funcionalidades existentes para que el LLM entendiera la base de código. La capacidad del chatbot de explicar código y capacidades de negocio nos permitió comprender los fundamentos de cómo funcionaba sin necesidad de una lectura y análisis manual extensivo.

 

Sobre esta base exploramos qué tan rápido podíamos añadir nuevas funcionalidades. Creemos que muchas bases de código legacy carecen de una visión arquitectónica clara; por eso necesitamos extraer no solo conocimiento de negocio, sino también generar una explicación de cómo funciona todo el sistema en conjunto.

 

Dado que la mayoría de proyectos legacy en C++ usan CMake, experimentamos extrayendo un tipo específico de fragmentos en la fase inicial de ingesta, llamados packages, basados en información del archivo CMake. Después implementamos una vista de componentes agentic (nivel tres) basada en el modelo C4, que aplica el mecanismo de recorrido sobre los packages extraídos y sus resúmenes.

 

Esta vista utiliza los targets de compilación de CMake, que agrupan archivos fuente relacionados, como entrada. Creamos un elemento arquitectónico entre la vista de componentes (nivel tres) y la vista de código (nivel cuatro) del modelo C4, para conectar el sistema de build con la jerarquía del modelo C4. El analizador agentic de archivos, ya presente en CodeConcise, se usó para procesar archivos de lanzamiento de ROS2 e identificar las relaciones entre packages. Después los componentes pudieron heredar las relaciones de los packages subyacentes, ya que siempre existe una relación 1:n entre componentes y packages. Este enfoque de análisis agentic se eligió para facilitar la extensión hacia otros protocolos de comunicación asincrónica como SOME/IP y para demostrar cómo extraer información rápidamente en un entorno heterogéneo donde el análisis tradicional alcanza sus límites.

 

La imagen anterior muestra cuántos packages contribuyen a un componente, manteniendo las relaciones extraídas.

 

Lo que aprendimos

 

Observamos cómo la IA puede acelerar significativamente nuestra capacidad para comprender bases de código desconocidas. CodeConcise ofrece una flexibilidad considerable, adaptándose fácilmente a diferentes necesidades pese a algunos obstáculos técnicos iniciales.

 

Esta experiencia también demuestra el verdadero potencial de la IA, mostrando que, si se combina con prácticas sólidas de ingeniería, puede aportar beneficios sustanciales.

 

Sin embargo, también enfrentamos retos. Por ejemplo, tuvimos que implementar soluciones para los límites de contexto del LLM y manejar alucinaciones escribiendo mejores prompts. Además, la base técnica subyacente evoluciona rápidamente, lo que significa que aún es algo inmadura. Aun así, logramos demostrar cómo la IA puede ser utilizada para ayudar a resolver problemas complejos.

 

Un especial agradecimiento a mi equipo, Christoph Burgmer, David Latorre, Zara Gebru, no solo por el trabajo en el proyecto, sino también por su valioso feedback..

 

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 Thoughtworks.