¿Puede la IA sustituir a un programador?
Tags: spanish, ia, python, ai
Published: 2024-04-25 09:32:53

---
title: ¿Puede la IA sustituir a un programador?
series: Rumiando
published: true
description: Comparativa entre motores de IA. ¿Cómo de bueno es el código?
tags: #spanish #ia #python #ai
cover_image: https://upload.wikimedia.org/wikipedia/commons/6/64/Dall-e_3_%28jan_%2724%29_artificial_intelligence_icon.png
# Use a ratio of 100:42 for best results.
# published_at: 2024-04-24 10:38 +0000
---

La IA (inteligencia artificial, o AI *artificial intelligence* por sus significado en inglés), ha irrumpido con fuerza en nuestro mundo. Esta irrupción, por desgracia, no ha venido sino acompañada con todo tipo de presagios y previsiones agoreras. Especialmente, ha habido muchas de estas previsiones relacionadas con profesiones. Con profesiones que se van a acabar, claro.

Estas previsiones sobre profesiones que se van a terminar también las hay para todos los gustos: desde simples mentiras (¿entusiastas, se puede predecir el final de una profesión de manera entusiasta?), a apreciaciones verdaderas que deben aún así aceptarse con matices.

Sí, hay empleos que van a desaparecer. No solo por la IA, sino porque los empleos llevan desapareciendo constantemente a lo largo de nuestra historia (a medida que se añaden otros nuevos, por cierto). Es normal. Por ejemplo: telefonistas (encauzar llamadas al destinatario), ascensoristas (manejo del ascensor), fareros (mantenimiento de faros), faroleros (encender farolas por la noche y apagarlas por la mañana)...

Por ejemplo, se supone que los profesores desaparecerán porque los alumnos podrán aprender de todo simplemente tecleando la pregunta en un chat de IA. Por supuesto, esto es falso. Aunque obtener una respuesta en un chat implicase directamente asimilar el conocimiento pedido, para algo así sería necesario que el alumno tuviera dos aptitudes: el ser autodidacta y el tener una gran base para poder comprender los nuevos conocimientos. Es tan raro encontrar estudiantes verdaderamente autodidactas como que tengan la base necesaria (algo que nos lleva recursivamente a la premisa inicial). Y eso sin tener en cuenta la necesidad tener que de realizar las preguntas adecuadas para progresar en tus estudios...

Otra profesión que desaparecerá, según los agoreros de la IA, es la de programador. Al fin y al cabo, ¿para qué necesitas un programador, cuando puedes pedirle el código fuente a ChatGPT o herramientas de IA similares? En realidad, en el caso de que realmente se usara, es necesario un programador para discernir *si el código proporcionado es de calidad o no*.

## La comparativa

Para decidir si es posible o no reemplazar a los programadores con ChatGPT o similar, resolví presentar el mismo ejemplo de código a varios motores de IA: [ChatGPT](https://chatgpt.org/chat), [Blacbox](https://www.blackbox.ai/), [Gemini](https://gemini.google.com), [Copilot](https://copilot.microsoft.com) y [AIChat](https://deepai.org/chat).

> Necesito código Python para una clase que contenga el nombre, apellidos. email y fecha de nacimiento de una **Persona**. Toda esta información será accesible a través de *propiedades de solo lectura*. Un método *str* convertirá la información en cadena de caracteres.
> Además, la clase **Empleado** derivada de persona contiene la información de la empresa para la que trabaja, lo publica como *propiedad de solo lectura*, y también provee de un método *str* que convierte toda la información a cadena de caracteres.
> La clase **Estudiante** derivada de persona contiene la institución, el nombre del grado y el número de curso (1 a 4). Toda esta información también se publica como *propiedades de solo lectura* y también ofrece un método *str* que convierte toda la información a cadena de caracteres.
> Finalmente, la clase **PersonaRepo** contiene una lista de personas, un método *str* que devuelve toda la información de todas las personas (una por línea), y una propiedad de solo lectura *personas* que devuelve una lista de personas. Además, el método *busca* admite una lambda que permite ejecutar un filtrado de las personas almacenadas.

Este es un ejercicio típico que puede formar parte de un examen para resolver delante de un ordenador (sí, [soy profe](https://jbgarcia.webs.uvigo.gal/). Oye, tiene que haber de todo). La idea detrás de este ejercicio es demostrar que el alumno es capaz de manejar conceptos como encapsulación (ocultación de atributos), herencia (como reuso de código y representación del principio de Liskov), o polimorfismo(en este caso a través de una colección y de la reescritura de métodos).

Todas estas características del ejercicio nos lleva a que... se trata de un ejercicio que tan solo emplea las funcionalidades básicas del lenguaje de programación: no hay nada complejo o específico. Además, el enunciado está tan "mascado" que no debería haber problemas de comprensión.

La siguiente tabla muestra si el código fuente devuelto por los diferentes motores de IA es directamente ejecutable o no. He descartado errores de formato (Python es especialmente sensible a esto), y es que sorprendentemente **GPTChat** y **AIChat** no se aclaran con dónde empieza el código fuente y dónde acaba en el texto generado.

|Nombre       |Ejecutable|Código fuente     |
|-------------|----------|------------------|
|**ChatGPT**  |No        |[Código ChatGPT](https://ideone.com/5Eg96w)|
|**Blackbox** |No        |[Código Blackbox](https://ideone.com/lRFi5C)|
|**Gemini**   |Sí        |[Código Gemini](https://ideone.com/ZD6pv8)  |
|**Copilot**  |Sí        |[Código Copilot](https://ideone.com/U9fCFE) |
|**AIChat**   |No        |[Código AIChat](https://ideone.com/OGpIQO)  |


Las características de cada código tipo son las que aparecen en la siguiente tabla. Las etiquetas `ERR` indican características que impiden que el código funcione, mientras que las etiquetas `SEM` indican, en definitiva, problemas de comprensión del problema.

|Código      |Rasgos                                 |
|------------|---------------------------------------|
|**ChatGPT** |`ERR`: init sin guiones bajos.         |
|            |`SEM`: No usa datetime para fechas     |
|            |`SEM`: Devuelve `PersonaRepo._personas` directamente.|
|            |Atrs. privados con un _                |
|            |Utiliza bucles en lugar de comprensión de listas|
|**Blackbox**|`ERR`: `PersonaRepo._persona` en vez de `PersonaRepo._persona`|
|            |`SEM`: Devuelve `PersonaRepo._personas` directamente.|
|            |Atrs. privados con un _                |
|            |Utiliza comprensión de listas          |
|            |Ejemplo detallado, incluido `PersonaRepo.buscar`|
|**Gemini**  |`SEM`: No usa datetime para fechas     |
|            |`SEM`: Devuelve `PersonaRepo._personas` directamente.|
|            |Atrs. privados con un _                |
|            |Utiliza bucles en lugar de comprensión de listas|
|            |Ejemplo detallado, incluido `PersonaRepo.buscar`|
|            |Provee muchos comentarios al código.   |
|**Copilot** |`SEM`: No usa datetime para fechas     |
|            |`SEM`: Devuelve `PersonaRepo._personas` directamente.|
|            |Atrs. privados con doble _             |
|            |No genera código de prueba             |
|**AIChat**  |`ERR`: init sin guiones bajos.         |
|            |`SEM`: No usa datetime para fechas     |
|            |`SEM`: Devuelve `PersonaRepo._personas` directamente.|
|            |Atrs. privados con un _                |
|            |El código de prueba no funciona bien.  |

## Análisis
### Errores sintácticos

Lo normal sería esperar que el código generado por una IA no tenga errores. Al fin y al cabo, se va a utilizar como "parte dada" de una app y no se va a cuestionar su funcionalidad. O se quiere aprender de este código, y por tanto sería muy confuso que aparecieran errores. Bueno, pues aparecen errores que impiden que se ejecute el programa. En cualquier caso, son los errores más sencillos de resolver.

- **`ERR`: init sin guiones bajos.**: El código contiene métodos que deberían tener el nombre `__init__()` (el inicializador de Python) y han sido generados como `init()`. Esto es particularmente grave, ya que este simple cambio de nombre hace que la clase no tenga un inicializador y por tanto no se puedan crear objetos en su interior. (Sé lo que estás pensando, la línea que separa un error semántico de otro sintáctico es muy fina en Python. Lo que he decidido es poner como errores fallos que generan un mensaje de error, impidiendo la ejecución del programa.)

- **`ERR`: `PersonaRepo._persona` en vez de `PersonaRepo._persona`**: Este parece un tipo de error cometido de forma más propia por una persona que por un ordenador, al "olvidar" que el atributo es `_personas` en lugar de `_persona`.

### Errores semánticos

Los errores semánticos son todavía más graves; implican que no se ha comprendido correctamente el enunciado, aunque el programa generado funcione. Es necesario tener un conocimiento profundo para poder corregirlos.

- **`SEM`: No usa datetime para fechas**: En lugar de utilizar un objeto **datetime** para representar las fechas, se emplea una cadena de caracteres. Aunque para casos triviales (como este), puede funcionar, en general hay muchos detalles que hacen necesarios utilizar un objeto de la clase proporcionado por la librería estándar. Husos horarios, cambios en el calendario, formato de fecha de cada país... provocan errores que se evitan casi completamente utilizando un soporte adecuado.

- **`SEM`: Devuelve `PersonaRepo._personas` directamente**: Independientemente del motor de IA utilizado, el contenido de la propiedad `personas` obtenido es siempre el mismo: `return self._personas`. Esto es un gran error, de hecho [devolver directamente una colección cualquiera, puede llegar a convertirse en una vulnerabilidad](https://dev.to/baltasarq/c-hackeo-nocturno-4aam). En resumidas cuentas, si creamos una clase alrededor de una colección es, al fin y al cabo, para limitar el acceso a dicha colección. Devolviendo directamente la colección, lo que estamos haciendo es ofrecer una vía directa para que el usuario de la clase  en realidad se la salte y haga los cambios que quiera. Así, la clase deja de ser necesaria, en contra de lo diseñado. La forma de solucionarlo es en realidad muy sencilla si se sabe cómo. Basta crear una copia de la lista y devolverla en lugar de la original, por lo que solo sería cuestión de sustituir esa línea por `return list(self._personas)`

### Detalles

Lo siguiente no son fallos graves, pero merece la pena comentar estas *características*.

- **Atrs. privados con un/doble _**: En Python no existe, como tal, una forma de indicar que un atributo es privado. Como convención, se indica que se añada un guión bajo delante. Estos atributos siguen siendo accesibles, pero sabes que no están pensados como parte de la interfaz pública de la clase. Solo **Copilot** utiliza el doble subrayado precedente, que hace que Python lance el *name mangling* (ocultación de nombres), de manera que es "más difícil" (aunque en absoluto imposible), acceder a ese atributo. Teniendo en cuenta que se trata de código generado automáticamente, para evitar posibles conflictos entre nombres de atributos, sería más apropiado emplear el doble subrayado.

- **Utiliza comprensión de listas**. Aunque existen muchas maneras de lograr automatizar un problema, en Python son preferibles aquellas más compactas, dado que al ser de naturaleza interpretada recursos como la *comprensión de listas* mejora muchísimo el rendimiento. Por ejemplo, en el método **PersonaRepo**.`buscar(pred)` se puede crear un bucle y añadir en cada vuelta a la persona que cumpla con el predicado *pred*. O se puede crear una comprensión de listas tan directa como `return [p for p in self._personas if pred(p)]`, como hace el código devuelto por **Blackbox**, o `return filter(pred, self._personas)` como hace **Copilot**. El resto utiliza bucles *manuales*, que no denotan un conocimiento profundo de Python. Quizás en el caso de **Gemini**, se podría argüir que se centra más en una explicación (con tanto comentario y bucles) para un principiante que en un código para tomar y utilizar (asumámoslo, la gran mayoría de los usuarios de estos servicios es lo que harán).

- **Ejemplo detallado, incluido `PersonaRepo.buscar`**: La mayoría de los motores de IA proveen un ejemplo de uso simple, mientras que **Blackbox** y **Gemini** ofrecen un ejemplo más exhaustivo, cubriendo más código del generado.

- **No genera código de prueba**: **Copilot** no se "molesta" en generar un código que pruebe su solución, mientras el resto, mejor o peor, sí lo hacen.

- **El código de prueba no funciona bien.**: **AIChat** ofrece un código de prueba que... no funciona, o al menos no funciona bien a la hora de mostrar los resultados. Muestra el contenido de una lista de objetos **Persona** directamente, lo que sabemos que visualizará algo como [Persona object, Persona Object...]. Lo correcto es convertir el resultado en una lista de cadenas de caracteres con `[str(x) for x in repo.buscar(lambda persona: persona.nombre.startswith("J"))]` y después pasarle esta lista a `str.join(", ", lista)` (sí, puede ser anidado directamente). O, para no complicarse la vida, hacer como **Blackbox**: `for p in repo.buscar(lambda persona: persona.nombre.startswith("J")): print p`.

Volviendo a la premisa: ¿los programadores van a quedarse sin trabajo? Va a ser que no. Esta tecnología está muy, muy verde, especialmente si tomamos en consideración que el ejemplo es muy sencillo (hasta le decimos directamente que utilice propiedades de solo lectura... en otro caso, el código generado no las incluye). Es de notar, además, que ninguno de los códigos generados refuerza la idea de que el grado solo puede tener valores de 1 a 4.

Si tenemos en cuenta que la IA actual es un modelo estadístico actuando sobre una cierta colección de conjuntos de código fuente, está claro que para conseguir una mínima calidad sería necesario vigilar dicho código de partida. ¿Tiene la calidad adecuada para ser parte del código de entrenamiento? En otro caso, el código necesario podría ser empleado como una referencia con respecto a "cómo se hace" algo, pero nunca como código a utilizar directamente. Y ya de sustituir al programador, mejor no hablar. A no ser que sea un programador muy malo, claro.