8 de septiembre de 2017

¿Puede la retroinformática darnos mejores programadores en el futuro? Este estudio cree que sí

La tecnología avanza a pasos agigantados. Lo que hace una década era state of the art queda relegado al olvido por nuevas soluciones y productos que resuelven nuestros problemas de una manera más eficiente. Sin embargo, esos viejos ordenadores de 8 bits pueden esconder el secreto detrás de una nueva generación de ingenieros informáticos más preparados que nunca. Al menos es una de las conclusiones de un artículo publicado por cuatro doctores ingenieros en informática de la Universidad de Alicante.

Explicando el bajo nivel de programación de los estudiantes es un artículo escrito por los doctores Francisco J. Gallego Durán -un clásico por estos lares-, Patricia Compañ Rosique, Rosana Satorre Cuerda y Carlos Villagrá Arnedo, ganador del Premio 2017 al mejor artículo de JENUI (Jornadas sobre Enseñanza Universitaria de la Informática) en el ámbito de SISTEDES (Sociedad de Ingeniería de Software y Tecnologías de Desarrollo de Software). En dicho artículo se plantea una problemática -el deterioro en la calidad de los programas de los estudiantes de cuarto curso-, se formula una hipótesis y se pone a prueba dicha hipótesis con una acción también con amplia cobertura en estas páginas: CPCRetroDev.


El problema


El análisis de cientos de ejemplos de código lleva a detectar un problema importante a la hora de formar buenos ingenieros, viendo cómo el código escrito por los alumnos de cuarto curso, alumnos a los que se les asume una serie de conocimientos suficientes, no llegaba al nivel esperado, mostrando severas carencias tanto en términos de aplicación de alto nivel como de conceptos fundamentales. No es que los programas no funcionen -nadie podría obtener un título si no es capaz de resolver las prácticas-, sino que el código generado dista de ajustarse a unos estándares de calidad exigibles a los que, no lo podemos olvidar, están a punto de ser ingenieros informáticos.

Los requerimientos a un ingeniero informático van mucho más allá de saber programar en tal o cual lenguaje; un buen ingeniero debe entender cómo funcionan las cosas para poder formular la forma más eficiente se resolver un problema. De ahí la crítica importancia de que, de manera aparentemente generalizada, los estudiantes de ingeniería, en un curso tan avanzado como es el cuarto, arrastren carencias que deberían estar solventadas desde los inicios de su carrera.

Primer diagnóstico


Tras analizar los datos y realizar una serie de encuestas entre los alumnos, se detecta que es un problema bastante generalizado, lo que implicaría una carencia en el propio proceso de enseñanza y aprendizaje. No es que la comunidad educativa haya dejado abandonados a los estudiantes, ni mucho menos, pues se han lanzado diversas iniciativas de cara a motivar a los estudiantes; es que éstos modelizan erróneamente los conceptos básicos de bajo nivel (del compilador hacia "abajo").

A esta hipótesis se llega tras cuatro años de observación y utilizando teorías actuales de psicología. El problema no radica en la dificultad per se de los conceptos básicos; es que no se les dedica el tiempo suficiente o no se les da la importancia debida en la actualidad. Así, mientras se le da mucha importancia a los niveles más altos dentro del modelo conceptual que sustenta el proceso para diseñar la solución a un problema (programa - saber manejar el lenguaje de programación de alto nivel), no se le da la suficiente a la otra parte de la ecuación (máquina -  bajo nivel).

Aunque hay ciertas diferencias curriculares en los primeros cursos de Ingeniería de cada Universidad, es común una cierta tendencia a pasar por alto el bajo nivel y optar por lenguajes de alto nivel, con predilección por la enseñanza de modelos y paradigmas, pero descuidando los cimientos sobre los que se asientan, en última instancia, esos conceptos mismos: media un abismo, en términos de conceptos, entre la ejecución de un binario por parte del procesador y el código fuente del que se generará ese binario.



Otro error determinante que suelen cometer algunos docentes es dar por sabidos conceptos básicos que para ellos son claros y están más que asumidos. A todos nos ha pasado alguna vez, sobre todo en materias de ciencias, que un profesor emplee conceptos sin explicar su significado, simplemente porque asume que deberíamos conocerlos, y no siempre es el caso. Otro ejemplo más tonto aún: cuando tuve conocimiento de este artículo por boca de Fran Gallego tuve que buscar en internet que significaba JENUI y SISTEDES ya que, en un pequeño lapsus, Fran dio por hecho que yo sabía a qué se refería y no vio la necesidad de explicarme el significado de dichos acrónimos.

¿Qué ocurre cuando los estudiantes modelizan erróneamente conceptos base? Pues, entre otros problemas, resulta en dificultades para implementar soluciones de software desde cero. Sin olvidar un problema mucho más grave aún: ni siquiera son conscientes de tener ese problema; enfrentados a su código y destapada la baja calidad del mismo, la respuesta de los estudiantes no podía ser más desoladora:

  • "Así funciona"
  • "¿Eso no lo optimiza el compilador?"
  • "El código lo copié y lo adapté"
  • "En la empresa X me han dicho que programo muy bien"
Como en cualquier proceso creativo, y la programación no deja de serlo, sacar a la luz este tipo de problemas, en un curso tan avanzado como es cuarto, causa frustración a los estudiantes, lo cual genera otro problema más: la motivación. Era hora de poner a prueba la hipótesis y buscar una solución.

Comprobando la hipótesis: CPCRetroDev


Con vistas a pasar de las palabras a los hechos, nace el CPCRetroDev. Cualquier lector de RetroManiac ya conoce a estas alturas la brillante iniciativa pedagógica que se esconde detrás del CPCRetroDev. La creación de videojuegos es una de las motivaciones principales de los estudiantes del Grado en Ingeniería Multimedia, por lo que ponerles manos a la obra es una motivación extra para los estudiantes. El hecho de tener que utilizar una máquina tan limitada como el Amstrad CPC, con su procesador de 4 MHz y sus 64 KB de RAM, puede suponer un factor desmotivante para algunos, pero resulta un reto para otros, con su factor extra de motivación.

Independientemente del caso, para lo que sirve la tarea es para que los estudiantes se den cuenta por sí solos de la baja calidad del código generado cuando los recursos no son ilimitados. Cuando cada byte de memoria y cada ciclo de reloj cuenta, cada instrucción superflua supone una losa en el resultado final del proyecto. Enfrentados con un problema de limitación de recursos, los estudiantes tienden a tomar en consideración todas las herramientas a su alcance, incluso aquellas que han podido desdeñar en el pasado, como pueda ser un dominio en profundidad del compilador.



Para observar hasta qué punto el CPCRetroDev y, por consiguiente, la programación en una máquina de recursos limitados como puede ser el Amstrad CPC, supone un verdadero espaldarazo a la hipótesis formulada previamente, se realizaron encuestas entre los alumnos antes y después de participar en la actividad. En dicha encuesta se observa un cambio interesante en relación a preguntas como «valora tu nivel de programación» o «qué deberías hacer para mejorarlo», lo que permite afirmar que el CPCRetroDev contribuye decisivamente a concienciar a los estudiantes sobre el problema de la calidad del código y a proporcionar una motivación extra para solventarlo.

¿Es el CPCRetroDev la solución al problema?


La respuesta a la pregunta es no. El CPCRetroDev ha servido para que los estudiantes sean conscientes de los hándicaps con los que llegan a un estadio tan avanzado de sus estudios, y aporta un extra de motivación, pero, en sí mismo, no ataca la raíz del problema. No confirma al cien por cien la hipótesis que explicaría la baja calidad del código escrito por los estudiantes, pero sí muestra los suficientes indicios acerca de por dónde pueden ir los tiros como para animar a otros investigadores a profundizar en el tema.

Por otro lado, las pertinentes explicaciones de conceptos y herramientas en clase, necesarias para que los alumnos puedan enfrentarse con cierta garantía al reto que supone crear un videojuego para una máquina limitada como es el Amstrad CPC, supone una buena base sobre la que empezar a corregir el problema. El hecho de que estos alumnos se enfrenten a veteranos de la escena de todo el mundo supone el enésimo aliciente para que se tomen muy en serio el tema y sean capaz de dar lo mejor de sí mismos. Nadie quiere empezar su futura y brillante carrera en el mundo de los videojuegos pariendo un "truño" de proporciones bíblicas que además quede a disposición de todo el mundo, dejando el pertinente rastro en Internet y pudiendo convertirse en un futuro dolor de cabeza a la hora de solicitar un empleo si caemos en las manos de un recruiter hábil.

La solución está en los orígenes: el ensamblador


Existe un cierto consenso ante la idea de que los chicos y chicas que tuvimos un ordenador de 8 bits en nuestra infancia e hicimos algunos pinitos en BASIC contábamos con una ventaja de base respecto a nuestros compañeros con menos suerte. El aprendizaje de ciertos conceptos de programación a una edad temprana nos proporcionó las herramientas para solucionar problemas básicos pero, lo que es más importante aún, nos dio una serie de habilidades lógicas a la hora de atacar los problemas, las temáticas o los proyectos.

De una manera similar a lo ocurrido hace décadas, el conocimiento del bajo nivel a la hora de programar, y el enfrentarse a una máquina de recursos limitados desde los inicios del proceso formativo en la universidad, puede suponer la diferencia entre buenos y malos programadores. Es por ello, con vistas a dar un paso más en la confirmación de la hipótesis a la vez que poner los primeros mimbres para resolver el problema, que desde este curso académico los estudiantes de la Universidad de Alicante estudiarán ensamblador de Z80 en el primer curso, sustituyendo a lenguajes de alto nivel, con vistas a reforzar el aprendizaje de los conceptos base mediante una correcta modelización mental.



Éste es un proceso que requerirá de su tiempo para comprobar si, tal y como plantea la hipótesis, da resultado, pero desde un punto de vista lógico todo parece indicar que así debería ser. Volviendo a nuestra común afición, tenemos también una buena noticia para nuestros lectores, al menos para aquellos que han tenido la paciencia de llegar hasta aquí: el curso de ensamblador de Z80, formado por material audiovisual desarrollado para un fácil entendimiento, estará disponible en un futuro cercano para todo el público, no solo los estudiantes de la universidad.

Volver la vista atrás para mirar al futuro


En resumidas cuentas, las máquinas de nuestro pasado como, en este caso, el Amstrad CPC, pueden jugar un rol primordial a la hora de enseñar buenos hábitos de programación a las futuras generaciones de ingenieros informáticos encargadas de maravillarnos con los últimos desarrollos en tecnología puntera. Se cierra así un círculo con los orígenes, en lo que casi es una alegoría de los tiempos pretéritos en el que el sabio, perdido el ardor de la juventud, transmitía su sabiduría a las nuevas generaciones, encargadas de mejorar el conocimiento depositado en ellas y transmitirla, nuevamente y con mejoras, a la generación siguiente una vez, alcanzada su edad madura.

Nadie hubiera pensado que una computadora de 1984, treinta años después de su lanzamiento, y un venerable lenguaje de programación como es el ensamblador, con más de 60 años a sus colectivas espaldas, podrían jugar un rol importante en la educación de las futuras generaciones de ingenieros, y sin embargo, aquí estamos, con serios indicios de que pueden ser la solución al problema de la errónea modelización de conceptos base de las Ingenierías Informáticas, resultando en la formación de mejores programadores. Y pensar en la de veces que nos dijeron que era una pérdida de tiempo...

Lee el artículo original "Explicando el bajo nivel de programación de los estudiantes" en la web de AENUI

15 comentarios:

  1. Ningún comentario? Imperdonable. Da gusto leer artículos tan bien redactados y tan interesantes como éste. Seguid así. Y no podía estar más de acuerdo con lo que dice el estudio. Pero también extendería el uso de programación "a la antigua" a los módulos de desarrollo de aplicaciones, ya que ahí nada ven de pseudo código, ordinogramas o lenguajes mas antiguos.
    Saludos!

    ResponderEliminar
  2. Siempre me he metido con el modo de programar "a lo Java". Lo llamo así no porque sólo pase en Java, sino que la primera vez que lo vi fue en este lenguaje. Uno daba por supuesto cosas como que un lenguaje interpretado tipo Perl y demás había cosas que podías pasar por alto. Normalmente, estos scripts están hechos para funcionar, son pequeños y la calidad, eficiencia y demás no es muy importante. Si lo fuera, escogerías un lenguaje tipo C o similar.

    Pero con Java, la gente hace programas inmensosque tiran recursos sin más. No se optimiza, lo que prima es que funciona a cualquier coste, y si va lento o consume mucha memoria pues que se meta más hardware, que es barato. Así que a nadie le interesa optimizar, y te encuentras que con una máquina con 4 gigabytes de RAM intentas hacer algo que hacías con 4 megas perfectamente, y notas que el ordenador no tira bien, lo hace peor que hace 20 años. Y te recomiendas que subas a 8 gbytes. En fin... que creo que no es necesario bajar a los 8 bits, pero se pueden aprender muchas cosas a partir de ahí.

    ResponderEliminar
    Respuestas
    1. Esto es recurrente. Aún me acuerdo cuando la gente comparaba la velocidad y el tamaño de un programa en ensamblador y otro compilado en C para concluir lo mismo que comentas ahora.
      Luego fue el C++ y ahora toca Java. Se puede hacer malos programas en Java, en C on ensamblador. Lo que sucede es que en Java, por la razón que sea se programa más. Al programar más aparecen peores programas y la gente concluye que si Java esto o Java lo otro. Existen excelentes programas hechos en Java y programas penosos hechos en C o, sobretodo, en C++ y eso no concluye nada.

      Eliminar
    2. Como decía, esto no pasa en Java, y no quiere decir que un programador, por usar Java, sea malo. Cuanto más te alejas de la máquina, menos programas para ella. Desde un punto de vista funcional eso es bueno, porque te centras en resolver el problema en vez de hacerte entender con el procesador. Pero de cara a la eficiencia...

      En el caso de Java, el 80% de los programadores que me he encontrado dedican más tiempo a escribir documentación que a optimizar. Lo cual sería bueno... si no fuera porque nadie documenta, como mucho unas líneas de descripción de lo que hace cada clase en el código y tira de javadoc. Pero bueno, esa es otra historia.

      Mi comentario no va en plan guerra de lenguajes, es sobre la actitud de programadores de lenguajes de muy alto nivel, donde la mentalidad es que la hora de programador es mucho más cara que el hardware y nadie pierde el tiempo optimizando. Si funciona, palante, aunque desperdicie recursos innecesariamente. Eso pasa en cualquier lenguaje.

      Por ejemplo, hace 6 años tuve que optimizar un script que estaba en bash y utilizaba awk y perl. El script necesitaba más de 48 horas en terminar, y debía ejecutarse diaramente para procesar un fichero, con lo que debería terminar de procesar como mínimo en el mismo día en que se lanza. Tras mi optimización se quedó en menos de media hora de media en tiempo de ejecución. ¿Dónde estaba el problema? Pues por ejemplo que la entrada había que convertirla a unos valores. Eso se hacía con un script de awk. Pero en vez de ejecutarlo una vez para todos los valores y dejarlos en memoria convertidos, cada vez que utilizaba uno llamaba al awk con un grep. Y así con todo. No se necesita Java para desperdiciar recursos y tampoco se necesita C o ensamblador para buscar optimización, a veces con cosas tontas como que comparar enteros es más rápido que comparar los mismos valores como cadena ya te puede ahorrar mucho tiempo de procesamiento -esto fue otra cosa que ahorró como un 80% de tiempo en otro script en Python-, y eso no parece saberlo todo el mundo, y no tiene que ver con el lenguaje, sólo que es más normal verlo en gente acostumbrada a programar alejada de la máquina

      Eliminar
  3. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  4. Al hilo de este artículo, debemos reconocer que es sin duda impresionante el campo que abre la necrocomputación. Un buen amigo con el que suelo tratar estos y otros temas "retro" me contaba hace no mucho:

    ... "El año pasado estuve en el FOSDEM, una convención de desarrolladores de software libre que se hace en la universidad de Bruselas. Una de las charlas a las que asistí fue la de "Necrocomputación", que es una variante de la retrocomputación. Se trata de coger un software de hoy en día e intentar ejecutarlo en una máquina antigua. El ejemplo que pusieron fue el intento de ejecutar en un VAX de finales de los 70 una versión moderna de la base de datos PostgreSQL (es la base de datos que usa yahoo, por ejemplo). Obviamente no arrancaba, así que tuvieron que modificar el código de PostgreSQL para optimizarlo y que corriera en esa máquina. El resultado es que las modificaciones se pudieron incorporar al código oficial de PostgreeSQL de tal manera que incrementó su rendimiento al ejecutarse en sistemas actuales. El tema es que una serie de variables estaban declaradas como "float", pero las máquinas VAX no manejaban números en coma flotante (¡no saben operar con decimales!). Descubrieron que esas variables se podía declarar como "integers" sin problema. Y eso es mágico, porque un ordenador tarda muchísimo menos en operar con integers que con floats. Así que la retrocomputación no es sólo un tema para nostálgicos, hoy en día tiene una utilidad muy interesante."

    Creo que este puede ser uno de los objetivos principales que se persiguen en el enfoque del "mago" Fran Gallego en la formación de futuros ingenieros.

    Lo cierto es que yo mismo tenía pensado abordar un tema relacionado con el futuro de la retroescena en el próximo número de mi webzibe FINDE'S RETRO (que no sé cuando tendré a punto) y en el que reflexiono acerca del futuro del desarollo homebrew.

    Saludos

    ResponderEliminar
  5. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  6. Tengo una duda: ¿por qué Z80 y no 6502? ¿Alguna razón concreta o sólo porque el CPC era la plataforma que mejor manejaba quien lo decidió?

    ResponderEliminar
    Respuestas
    1. No hay ninguna razón especial para elegir Z80 o 6502, como podía haberse elegido 8080, 6510 o incluso 68000. Cualquiera es igual de válida. De hecho, conocer varias es incluso mejor. Pero el tiempo es limitado y hay que escoger una. Elegimos Z80 por la amplia variedad de dispositivos que lo tienen y que son de potencial interés para los estudiantes (Master System, Game Boy*, Microordenadores, etc) y porque ZX Spectrum y CPC en particular son máquinas fáciles de conseguir y muy fáciles de dominar. Pero como digo, puedes encontrar argumentos igualmente válidos a favor de 6502, 8080, 6510... Pero hay que escoger uno: no se puede ir a por todos a la vez ;)

      Eliminar
    2. Suponía que sería por eso. Sólo lo preguntaba porque tengo oído que el 6502 es más fácil de programar. Repito: oído, que no tengo ni idea de ensamblador.

      Eliminar
  7. Me gustaria acceder al curso gratuito de progtramar ensamblador de z80

    ResponderEliminar
    Respuestas
    1. En las próximas semanas se liberará para todo el mundo según nos comenta el responsable del proyecto. Informaremos de ello cuando llegue el momento :)

      Eliminar
  8. Felicidades por el artículo!
    Encantado de ver cómo se le da visibilidad a estas cosas.
    Respecto a si programas en C eres un warrior y si programas en Java eres un mierdas, lo preocupante es no saber lo que pasa por debajo cuando ejecutas una función, porque se puede programar a alto nivel en los dos lenguajes.
    Programar con recursos limitados (a bajo o alto nivel) es lo que te hace optimizar y economizar el código.
    Felicidades de nuevo a retromaniac y a @FranGallegoBR !

    ResponderEliminar
    Respuestas
    1. No es un tema de C o Java. Un mal programador no hace buenos programas por cambiar de lenguaje, de hecho te diría que probablemente los haga peores porque el compilador le dejará más decisiones a él, y no es bueno ;)

      El problema es que si tienes una máquina muy potente, las chapuzas que tiran recursos funcionan bien, el sistema se lo traga y la velocidad de ejecución puede ser aceptable. Pero una ñapa como esa en un sistema más limitado o no funciona o va tan lento que te obliga a pensar de otra forma. Y esa forma, pensando no en lo que es más cómodo para mí sino en lo que va mejor para la máquina que está corriendo debajo, es de lo que se trata. Por su naturaleza, C está más cerca de la máquina que Java, con lo que hay cosas que Java hace por ti que C no -por ejemplo, gestionar tu propia memoria-, con lo que te obliga a tener en cuenta cosas que Java no. Pero eso no significa que un programador de C sea mejor que uno de Java, más pro o lo que sea.

      Eliminar