Hace quince años, programar era cosa de minorías. Dominar PHP significaba entender el modelo de peticiones de Apache, sufrir las rarezas de los arrays de PHP 4 y memorizar el manual de mysql_* hasta interiorizar que la inyección SQL no es una broma de conferencia, sino una sentencia de muerte para tu base de datos. La información escaseaba, los foros eran templos de conocimiento fragmentado, y construir algo mínimamente útil costaba años de tropiezos.
Hoy cualquiera con una cuenta de chatbot genera un plugin de WordPress en treinta segundos. Es democratización pura, y me parece bien. Pero tiene un efecto colateral que casi nadie quiere nombrar: hemos confundido escribir código con construir software. No son lo mismo. Ni siquiera son parientes cercanos.
Apaño disfrazado de solución
Lo veo cada día. Llegan a nuestros servidores fragmentos de «soluciones» que funcionan justo hasta que dejan de hacerlo.
Un formulario de pagos que no sanitiza entradas. Un endpoint REST que filtra datos de usuario porque el meta_query se generó por iteración, sin caché ni límites. Un script de «optimización» que revienta procesos de MariaDB porque su autor confundió una conexión persistente con un agujero negro de memoria.
Ese código funciona, en el sentido más pobre del término: pasa el test de «clic, mira, sale dinero». Pero no es un producto, es un apaño con aspiraciones. Y en cuanto se expone a Internet deja de ser un fallo funcional para convertirse en vector de ataque. Los firewall bloquean a diario bots de IA que escanean vulnerabilidades con la misma eficiencia con la que indexan contenido, y la mayoría de esas vulnerabilidades no vienen de software sofisticado: vienen de «soluciones rápidas» copiadas de un foro sin pensar en permisos, en nonce checks, en que $_GET no es tu amigo.
El problema no es la falta de intención. Es la falta de disciplina.
El código que funciona no es el código que sobrevive
Aquí entran herramientas que forman parte del día a día y que no uso como ritual burocrático ni para presumir en GitHub, sino como filtros de realidad: PHPUnit, PHPCS y PHPStan nivel 9. La diferencia entre amontonar palos hasta que la corriente amaine y diseñar una presa que aguante temporadas, escale sin inundar aguas arriba y se pueda inspeccionar compuerta a compuerta sin vaciar el embalse.
PHPUnit: el contrato antes que el código
PHPUnit no es una herramienta de testing, es una herramienta de diseño. Escribir el test antes que la implementación te obliga a definir el contrato: qué espera tu código, qué devuelve, qué hace cuando las cosas se tuercen. Código sin tests es una promesa sin testigos, y las promesas sin testigos se rompen. Siempre.
En mi stack habitual (PHP 8.4, OPcache, JIT desactivado) los tests no son opcionales: son la documentación viva de lo que el sistema debe garantizar. Si un refactor rompe un test, ese refactor no entra. Punto. Sin «pero en mi ordenador funciona».
PHPCS: la coherencia como señal de cordura
Un código con estilo inconsistente no es un detalle estético, es la prueba de que lo han tocado tres «yos» distintos sin coordinarse, y de que el cuarto (el de dentro de seis meses, a las tres de la mañana, resolviendo un incidente mientras Netdata no para de pitar) no va a entender qué pretendías.
Y más allá de la forma, PHPCS caza patrones peligrosos: variables sin usar, funciones obsoletas, constructores que no respetan la firma esperada. Es el primer filtro antes de que nada toque el repositorio.
PHPStan nivel 9: la humildad como herramienta
PHPStan nivel 9 es lo más parecido a un antídoto contra la arrogancia del programador. Te avisa de «esto puede fallar» justo donde tú, optimista, solo ves éxito. Al migrar mi stack a PHP 8.4, PHPStan fue quien señaló los mixed colándose por código mal tipado, los arrays que prometían ser string[] y podían ser cualquier cosa, las funciones que aseguraban devolver un objeto y se olvidaban del caso en que la base de datos devolvía false.
Programar sin análisis estático es conducir sin cinturón por una carretera que casi siempre está vacía. Funciona hasta que no. Y cuando falla, falla en producción, con datos reales, y con tu nombre en el git blame.
El producto es más que la suma de sus líneas
No todo el que programa construye producto, y esa distinción se va a volver decisiva. Programar es escribir instrucciones para una máquina. Construir producto es anticipar fallos humanos, casos límite, latencia bajo carga, la ley de Parkinson aplicada a los datos («los datos se expanden hasta llenar el espacio disponible») y la certeza de que alguien usará tu software de una forma que nunca imaginaste.
Dejar ese apaño en un repositorio público (o peor, en un plugin activo en cientos de sitios) es externalizar el riesgo. Es convertir tu falta de tiempo, o de conocimiento, en deuda técnica que pagan otros. Tengo alertas de latencia anómala en Netdata y detect-ai-bots.sh corriendo contra mis logs para saber quién escanea qué, pero ninguna herramienta de infraestructura compensa un producto mal concebido desde su arquitectura.
Y esto tiene lectura económica, no solo técnica. El mercado ya no premia al que «lo saca rápido». Premia al que lo saca y no tiene que refactorizar a los seis meses porque un cliente filtró datos personales y la AEPD empieza a hacer preguntas incómodas. Premia al que duerme tranquilo porque se lanzan pruebas, análisis estático y revisión de seguridad antes de que un solo byte llegue a producción.
El código generado por IA no es malo por definición. El problema es el código generado por alguien que no entiende por qué se generó así, que no puede evaluar su seguridad, que no sabe dónde termina el apaño y empieza el riesgo. Eso sí es un accidente esperando víctima.
No es sintaxis, es responsabilidad
La democratización de programar es irreversible y, en el fondo, buena. Pero hay que dejar de venderse la moto de que «todo el mundo puede programar» implica «todo el mundo produce software de calidad». Es tan falso como pensar que, porque cualquiera sabe atornillar una tabla, cualquiera puede diseñar el mobiliario de una biblioteca pública.
Quien realmente construye producto integra estas herramientas no como adorno, sino como arquitectura: PHPUnit para fijar comportamientos antes de que la euforia del echo nos ciegue, PHPCS para que el código lo lea un humano y no solo un intérprete, PHPStan para que el rigor de tipos nos proteja de nosotros mismos. Y, sobre todo, la humildad de saber que un código que solo funciona en tu máquina, con tus datos de prueba, no es un logro. Es un espejismo.
El futuro no es de quien genera líneas más rápido. Es de quien genera líneas que otros pueden mantener, auditar y dejar en producción sin goteras.
El otro día un script auto-generado en plan emergencia y casi sin revisar empezó a saturar conexiones contra MariaDB porque no usaba prepared statements. El sistema de alertas saltó en un par de minutos.
El código funcionaba. El producto, no.
Y esa es toda la diferencia.





Deja una respuesta