Actualizando código PHP con la ayuda de IA y Rector


Apuesto a que, como integrador o desarrollador de proyectos, alguna vez te han ofrecido encargos que, al conocer los detalles, de inmediato rechazaste o te hubiera gustado rechazar. Y es que siempre aparecen razones varias o dificultades para decir “no”, algo totalmente normal si eres freelance y llevas poco tiempo trabajando por tu cuenta.

La deuda técnica del legacy code

Si no eres de los afortunados que logran siempre evadir los problemas, seguramente habrás tenido que enfrentarte a algún sitio web con PHP obsoleto, sin soporte, o con extensiones o temas descatalogados, o con alguno de estos code smells: código mal escrito, anticuado, extenso, enigmático, o simplemente código extenso o que realiza tareas incomprensibles.

En resumen, el abandono de todo ese código, que llamamos legacy code, acaba provocando una deuda técnica (en el fondo es tiempo y dinero), conocida como technical debt (deuda tecnológica).

Sí, yo también me he enfrentado al legacy code

Uno no empieza su carrera profesional siendo un excelente integrador o desarrollador. Todos empezamos en algún instante, desarrollando e integrando con los conocimientos de que disponemos y el resultado no siempre es modélico.

En mi caso, y de aquí surge escribir el artículo, yo mismo recibí un encargo: tras una auditoría de seguridad, el cliente se vio forzado a enfrentar la deuda técnica y actualizar todos los sitios a la última versión de PHP.

Incluso haciendo un buen trabajo, con el tiempo las plataformas evolucionan y el código, sin más, envejece y necesita de cuidados y actualizaciones.

La importancia de invertir en mantenimiento 

Antes de entrar en materia de soluciones, dejadme un último bloque para que me desahogue:

Y es que, en mi día a día, atendiendo soporte en un alojamiento, me enfrento de forma recurrente a usuarios, que para pedir ayuda, descargan la frase:

– no he hecho nada y la web ha dejado de funcionar – 

Puedo deciros que he desarrollado una especie de protección empática y nunca pierdo los nervios. Simplemente, respiro hondo y les relato con más o menos tecnicismos que las webs son en el fondo entes vivos, dentro de un ecosistema de extensiones, servicios y sistemas operativos cambiantes y que, por lo tanto, necesitan de cuidados.

La clave para que la web no deje de funcionar está en invertir en mantenimiento. Es necesario reservar tiempo y presupuesto para ir evolucionando el código, o simplemente gestionando actualizaciones. En algún entorno de desarrolladores habrás oído reclamar que es necesario invertir, para reducir la deuda técnica.

Enfrentarse al legacy code ya no es una tortura

Antes de la aparición de las IA (tipo ChatGPT u otros similares) no habría escrito este titular.

Sí, es cierto, hace tiempo que para PHP tenemos una muy buena herramienta de refactorización de código, Rector. Pero es que la combinación ChatGPT 4 y Rector, ha resultado ser en mi caso un cambio radical en la velocidad y la manera de enfrentar código desactualizado. Es por ello que os explico como lo hago yo con estas herramientas, pero cada uno puede elegir herramientas similares si son más de tu gusto.

Veamos, pues, qué aporta cada pieza.

Refactorizar con ChatGPT

Lo primero que tenemos que tener en cuenta con ChatGPT es que probablemente excedamos el contexto que nos da el prompt. En ChatGPT 4 podemos procesar un máximo de 4096 tokens

Por ejemplo en esta simple línea de código:

echo "Hello world!";

Estamos usando 7 tokens: 

  1. echo
  2. «
  3. Hello
  4. world
  5. !
  6. «
  7. ;

Mayor contexto con Code Interpreter de ChatGPT

Una de las opciones recientes que incorpora, en beta a fecha de este artículo, es la opción Code interpreter.

Lamentablemente, el intérprete solo trabaja en Python, ¡pero la buena noticia es que el contexto se duplica pasando de 4092 a 8192 tokens!

Activa Code Interpreter, de ChatGPT

Puedes activar la opción desde Settings & Beta que encontrarás en el menú de tu perfil. 

Se abrirá la ventana Settings y en la sección Beta features puedes habilitar la opción Code interpreter.

Tras activar Code Interpreter podrás elegir la opción al crear un nuevo chat.

Otra de las ventajas es que esta nueva opción nos permite subir archivos Upload. Con esta opción evitarás contaminar el contexto del chat con idas y venidas de código.

No obstante, si subes un archivo, el contenido de ese archivo se descuenta del total de tokens disponibles. Por lo tanto, si un archivo consume, por ejemplo, 6000 tokens, solo quedan 2192 tokens para la conversación interactiva en el chat.

A modo de ejemplo, una solicitud o prompt, que me resultó escueta y efectiva, fue la siguiente:

¿Podrías darme una versión refactorizada a PHP8 de Pmain.inc usando "Best practices" y en un formato que pueda descargar?

Refactorizando con ChatGPT

Volviendo a mi tarea de refactorizar varias webs WordPress, me enfrentaba a dos problemas para los que necesitaba ayuda de ChatGPT:

  1. Entender el propósito de lo que hacían las funcionalidades añadidas en functions.php. En algún caso el archivo llegaba a las 1000 líneas de código.
  2. Actualizar plugins y temas desarrollados a medida. 

Teniendo en cuenta el tamaño del contexto y el procedimiento, ChatGPT resultó ser de gran ayuda para entender qué hacía cada una de las piezas a actualizar y en algunos casos, refactorizar el código.

Sin embargo, hay que tener en cuenta que ChatGPT se actualizó en septiembre de 2021 y por ejemplo, no es posible exigirle una refactorización a versión 6.3. En esa fecha WordPress iba por la versión 5.8.

Dejándome llevar por el positivismo de ChatGPT, le pedí refactorizar a la 6 y no pareció ser un obstáculo, como mínimo, para compatibilizar:

Respondió con recomendaciones, pero también con código:

Refactorizar PHP, con Rector

Rector es una herramienta gratuita y de código abierto escrita en PHP que te permite automatizar diversas tareas de refactorización

A diferencia de ChatGPT y las IA asistentes de código, esta herramienta no es capaz de reinterpretar el código, pero sí de corregirlo y hacerlo de una manera determinista. Es decir, para un mismo código de entrada, siempre producirá el mismo resultado. 

Rector tiene contexto ilimitado y refactorización en bloque

Además del determinismo, otra gran ventaja de Rector es que, esta vez sí, el contexto no es un problema. Rector es capaz de refactorizar gran cantidad de archivos y hacerlo en secuencia recorriendo la jerarquía de directorios que determinemos.

Rector está permanentemente actualizado

Rector permite trabajar con código tan antiguo como PHP 5.3 y refactorizar para hacerlo compatible con la última versión de PHP, a fecha de este artículo la versión 8.2.

Modernizar código PHP con Rector

A modo de ejemplo, a continuación, usaremos Rector para pasar un antiguo plugin de WordPress con código PHP5 obsoleto a la última versión.

Continúa leyendo para ver cómo instalar Rector en tu ordenador y configurarlo para que actualice todos los archivos del plugin con código obsoleto.

Instalar Rector con Composer

Una de las maneras más rápidas y sencillas de instalar paquetes PHP es usando Composer.
Ojo, para ejecutar Composer necesitarás disponer de PHP 7.2.

Sitúate en el directorio de trabajo, por ejemplo junto al directorio del plugin a reparar y ejecuta el siguiente código para instalar rector:

composer require rector/rector --dev

Configurar Rector

A continuación ejecutamos rector, con el único propósito de que nos asista en la creación del archivo de configuración:

Edita rector.php con tu editor preferido:

Por defecto, Rector incluyó en $rectorConfig->paths el directorio del plugin a reparar, si en tu caso no es así, simplemente corrige el emplazamiento. 

Ahora sólo queda indicarle que queremos actualizar a PHP 8.2. Nuevamente, la configuración por defecto de Rector casi está lista para usar. Tan sólo hay que descomentar las tres líneas de $rectorConfig->sets:

No entraremos en detalles pero es bueno saber que Rector lo puedes llegar a perfilar para adaptarlo a tu estilo de programación. No todos los cambios son de compatibilidad, muchas de las nuevas funcionalidades de PHP 8 son de estilo, por ejemplo la aplicación del patrón “early return” allí dónde se pueda.

Usar Rector para optimizar el plugin WordPress a PHP 8.2

Lo primero es ejecutar Rector en modo test o “dry” para ver que ocurre sin llegar a modificar los archivos:

vendor/bin/rector process --dry-run

A partir de ahí puedes decidir si ir paso a paso, reducir la cantidad de reglas o simplemente confiar. Siempre puedes volver al punto de partida… para eso tenemos a “git”.

Procede con los cambios simplemente retirando el atributo “--dry-run” del comando anterior:

vendor/bin/rector process

En todos los casos en que he refactorizado usando Rector, el resultado ha sido más que correcto. Pocos han sido los casos en los que he tenido que corregir algún bloque de código y siempre han sido correcciones de estilo.

Conclusión

Abordar código obsoleto “legacy” para ponerlo al día no suele apetecer mucho. No obstante, la llegada de las Inteligencias Artificiales, que por suerte parece no tener escrúpulos, son de gran ayuda para descifrar y adecentar código.

Si además lo combinamos con joyas como Rector, os puedo asegurar que por lo menos en mi caso, cuando me llega algún proyecto legacy por modernizar, ya no me suelo poner a llorar.

Deja una respuesta