Los peligros de las escuelas Java

Ahora que estamos en plena época de cambio de planes de estudio en Informática, aprovecho para ofreceros esta traducción libre del artículo de Joel Spolsky The Perils of JavaSchools. Aunque no estoy de acuerdo con todo lo que dice, nos hace pensar en si estamos haciéndolo bien. Nuevas formas para una disquisición de toda la vida…

Los peligros de las escuelas Java

Perezosos. ¿Qué fue del trabajo duro? Un claro signo de mi descenso hacia la senectud son las quejas y protestas sobre «la juventud de hoy» y de cómo ya no saben hacer ni harán cosas difíciles.

Cuando era joven, aprendí a programar en tarjetas perforadas. Si cometías un error, no disponías de esas modernidades como la tecla de retroceso para arreglarlo. Tenías que tirar la tarjeta y empezar de nuevo.

Cuando empecé a hacer entrevistas a programadores en 1991, solía dejarles usar cualquier lenguaje que les ayudara a resolver los problemas de codificación que les proponía. El 99% de las veces elegían C. Hoy en día, tienden a elegir Java.

Ahora bien, no me malinterpreten: no hay nada malo en Java como lenguaje de implementación. Un momento, quiero cambiar la frase anterior. No estoy intentando decir en este artículo que no hay nada malo en Java como lenguaje de implementación. Hay muchas cosas malas en Java, pero tendrán que esperar a otro artículo.

Lo que quiero decir es que Java no es, en general, un lenguaje de programación suficientemente duro como para poder discriminar entre grandes programadores y programadores mediocres. Puede ser un buen lenguaje para trabajar, pero ése no es el asunto de hoy. Iría incluso tan lejos como para decir que el hecho de que Java no sea suficientemente duro es una característica, no un fallo, pero que tiene ese problema.

Si pudiera resultar arrogante, desde mi humilde experiencia hay dos cosas que se enseñan tradicionalmente en las universidades como parte de los planes de estudio en informática y que mucha gente nunca llega a comprender del todo: los punteros y la recursividad.

La carrera [de informática] solía comenzar con alguna asignatura de estructuras de datos, con listas enlazadas y tablas de dispersión y uso intensivo de punteros. Tales asignaturas solían servir como filtros: eran tan difíciles que quien no pudiera soportar el desafío mental de los estudios de grado en informática abandonaría, lo cual era algo positivo, porque si crees que los punteros son difíciles, espérate a intentar demostrar algo sobre la teoría de coma fija.

Todos los chavales que resultaran brillantes en enseñanza secundaria escribiendo juegos de pong en BASIC para su Apple II, que acabaran en la universidad matriculados en CompSci 101, un curso de estructuras de datos, y que al llegar al tema de los punteros sus cerebros explotasen, se especializarían en Ciencias Políticas porque las escuelas de ciencias sociales les parecerían mejor idea. He visto todo tipo de cifras de abandono en informática y suelen estar entre el 40% y el 70%. Las universidades tienden a ver esto como un derroche; Creo que sólo es un sacrificio necesario de aquéllos que no van a ser felices o tener éxito en carreras relativas a la programación.

La otra asignatura difícil para muchos estudiantes de informática es aquélla donde aprenden programación funcional, incluyendo la programación recursiva. El MIT puso el nivel muy alto para dichos cursos, creando una asignatura obligatoria (6.001) y un libro de texto (Structure and Interpretation of Computer Programs de Abelson y Sussman) que se usó en docenas e incluso cientos de escuelas de informática como una introducción de facto a la ciencia de la computación. (Vd. puede, y debería, echar un vistazo a una antigua versión online de las clases)

La dificultad de dichos cursos es sorprendente. En la primera clase se aprende bastante de Scheme, y de inmediato se pasa a una función de coma fija que recibe otra función como su entrada. Cuando me peleé con dicha asignatura, CSE121 en Penn [State University], observé cómo muchos, si no la mayoría, de los estudiantes simplemente no lo consiguieron. El material era demasiado difícil. Escribí un largo y quejicoso mensaje al profesor diciendo que No Era Justo. Alguien de Penn debió escucharme (a mí o a alguno de los demás quejicas), porque ahora dicha asignatura se enseña en Java.

Me gustaría que no me hubieran escuchado.

Aquí está el debate. Años de quejas de estudiantes perezosos de informática como yo, unido a las quejas de la industria sobre los pocos especialistas en informática que se gradúan en las universidades americanas, han hecho palanca, y en la última década un gran número de otrora perfectamente buenas escuelas han cambiado 100% a Java. Es macanudo: a los reclutadores que usan «grep» para evaluar curricula vitae parece que les gusta y, lo mejor de todo, no hay nada suficientemente difícil en Java para filtrar a los programadores que no poseen la parte del cerebro que procesa los punteros y la recursividad, así que las tasas de abandono son más bajas, y los departamentos de informática tienen más estudiantes y presupuestos mayores, y todo es estupendo.

Los afortunados chicos de las escuelas Java nunca van a obtener extraños fallos de segmentación al intentar implementar tablas de dispersión con punteros. Nunca van a alcanzar desolados y delirantes enfados intentando empaquetar las cosas en bits. Nunca tendrán que hacer que su cabeza se las arregle con el hecho de que, en un programa funcional puro, el valor de una variable nunca cambia y, a la vez, todo el tiempo está cambiando. ¡Una paradoja!

No necesitan esa parte del cerebro para especializarse en una 4.0

¿Soy uno de esos viejos cascarrabias, como los Cuatro Yorkshiremen [de la parodia de los Monty Python], jactándose de lo duro que fui para sobrevivir a tanta dureza?

Jo…, en 1900 el latín y el griego eran materias obligatorias en la universidad, no porque sirvieran para algo, sino porque eran consideradas algo así como un requisito obvio para la gente educada. En cierto sentido, mi argumento no difiere mucho del de los defensores del latín (los cuatro de antes). «[El latín] entrena tu mente. Entrena tu memoria. Desembrollar una frase en latín es un ejercicio excelente de pensamiento, un rompecabezas intelectual, y una buena introducción al pensamiento lógico», escribía Scott Barker. Sin embargo no puedo encontrar una sola universidad que exija ya latín. ¿Son los punteros y la recursividad el latín y el griego de la ciencia informática?

Ahora bien, admito libremente que la programación con punteros no es necesaria en el 90% del código escrito hoy día y, de hecho, es verdaderamente peligrosa en el código en producción. Ok. Está bien. Y la programación funcional no se usa mucho en la práctica. De acuerdo.

Pero todavía es importante para algunos de los trabajos de programación más apasionantes. Sin punteros, por ejemplo, no se podría trabajar con el núcleo de Linux. No se puede comprender una sola línea del código de Linux o, de hecho, de ningún sistema operativo, sin comprender de verdad los punteros.

Sin comprender la programación funcional, no se habría podido inventar MapReduce, el algoritmo que hace a Google tan masivamente escalable. Los términos Map y Reduce vienen de Lisp y la programación funcional. MapReduce es, en retrospectiva, obvio para cualquiera que recuerde de la clase de programación equivalente a la 6.001 [del MIT] que los programas funcionales puros no tienen efectos colaterales y son por tanto fácilmente paralelizables. El mismo hecho de que Google inventara MapReduce y Microsoft no lo hiciera dice algo sobre por qué Microsoft está aún intentando hacer funcionar características básicas, mientras que Google se ha movido al siguiente problema: construir Skynet, el supercomputador masivamente paralelo más grande del mundo. No creo que Microsoft comprenda por completo cuánto de lejos están en la onda.

Pero más allá de la importancia a primera vista de los punteros y la recursividad, su valor real es que para la construcción de grandes sistemas hace falta esa clase de agilidad mental que se obtiene aprendiéndolos, así como la aptitud mental que se necesita para esquivar el filtro que suponen las asignaturas en que se enseñan. Los punteros y la recursividad exigen una cierta capacidad para razonar, pensar en forma de abstracciones y, lo que es más importante, contemplar un problema desde varios niveles de abstracción simultáneamente. Por eso, la capacidad para comprender los punteros y la recursividad está directamente correlada con la capacidad para ser un gran programador.

No hay nada en una titulación con todo en Java que filtre a los estudiantes que carecen de la agilidad mental para tratar con estos conceptos. Como empresario, he comprobado cómo el 100% de las escuelas Java han comenzado a producir como churros numerosos graduados en informática que, sencillamente, no son suficientemente despiertos como para trabajar de programadores en algo más sofisticado que Otra Aplicación Más de Contabilidad en Java, a pesar de que consiguieron pasar por los pelos del recién cursado trabajo de atontamiento. Estos estudiantes nunca sobrevivirían a un curso 6.001 del MIT o de un CS 323 de Yale y, francamente, ésa es una de las razones por las que, como empresario, un graduado en informática del MIT o de Yale tiene más peso que uno de Duke, que migró recientemente a Todo-en-Java, o de la Universidad de Pennsylvania, que sustituyó Scheme y ML por Java en un intento de enseñar lo que casi me mata a mí y a mis amigos, CSE121. No es que no quiera contratar a chicos brillantes de Duke y Penn –lo hago– sino que es mucho más difícil para mí averiguar quiénes son. Solía ser capaz de distinguir a los chicos brillantes porque podían destripar un algoritmo recursivo en segundos, o implementar funciones de manipulación de listas enlazadas con punteros tan rápidamente como podían escribir en la pizarra. Pero con el grado de las Escuelas Java, no puedo decir si pasan apuros con estos problemas porque les falta formación o si pasan apuros porque no poseen la parte especial del cerebro que van a necesitar para hacer un buen trabajo de programación. Pal Graham los llama Blub Programmers.

Es bastante malo que las Escuelas Java no filtren a aquéllos que nunca van a ser buenos programadores, algo que las escuelas podrían afirmar de forma justificada que no es su problema. La industria, o, al menos, los contratantes-que-usan-grep seguramente claman por que se enseñe Java.

Pero las Escuelas Java también fallan en entrenar a los cerebros para ser suficienmentente diestros, ágiles y flexibles como para realizar buenos diseños de software (y no estoy queriendo decir «diseño» OO, donde puedes pasar innumerables horas reescribiendo el código para ajustar tu jerarquía de objetos, o preocupándote de falsos «problemas» como tiene-un vs. es-un). Hay que entrenarse pensando en cosas con múltiples niveles de abstracción a la vez, y ese tipo de pensamientos es exactamente lo que hace falta para diseñar buenas arquitecturas de software.

Puedes preguntarte si la enseñanza de la programación orientada a objetos (POO) es un buen filtro sustitutivo de los punteros y la recursividad. La respuesta rápida es: no. Sin debatir sobre los méritos de la POO, no es suficientemente difícil como para filtrar a los programadores mediocres. La POO en las escuelas consiste más en la memorización de un manojo de términos como «encapsulación» y «herencia» y hacer exámenes de opción múltiple sobre la diferencia entre polimorfismo y sobrecarga. No mucho más difícil que memorizar fechas y nombres famosos en una clase de historia, la POO plantea desafíos mentales no adecuados para ahuyentar a los estudiantes de primer año. Cuando te enfrentas a un problema de POO, tus programas funcionan, sólo que son algo difíciles de mantener. Presuntamente. Pero cuando te enfrentas a los punteros, tus programas generan Fallos de Segmentación y no tienes ni idea de qué está pasando hasta que te paras, respiras, e intentas esforzar tu mente para trabajar a dos niveles de abstracción diferentes a la vez.

Por cierto, los contratadores-que-usan-grep hacen el ridículo aquí por una buena razón. Nunca he conocido a nadie que pueda escribir Scheme, Haskell y punteros en C que no pueda pillar Java en dos días, y crear código Java mejor que gente con cinco años de experiencia en Java. Pero intenta explicarle esto a la media de los parásitos de Recursos Humanos.

Aún hay más. La informática tiene que ver con pruebas (recursividad), algoritmos (recursividad), lenguajes (cálculo lambda), sistemas operativos (punteros), compiladores (cálculo lambda) — y en resumidas cuentas una escuela Java que no enseñe C y no enseñe Scheme no está enseñando realmente informática en ningún caso. Tan inútil para el mundo real es curtirse en el concepto de función como obvio es que es un prerrequisito de una escuela de grado en informática. No comprendo por qué los catedráticos en los comités curriculares de las escuelas de grado en informática han dejado que sus planes de estudio se entontezcan hasta el punto en que no sólo no producen programadores que funcionen, sino que ni siquiera pueden producir estudiantes de grado que puedan obtener un doctorado y competir por un puesto de trabajo. Un momento. No importa. Creo que lo comprendo.

De hecho, mirando hacia atrás e investigando la discusión académica que tuvo lugar durante el Gran Cambio a Java, uno se da cuenta que la preocupación mayor era si Java era suficientemente sencillo como para usarlo como lenguaje para la enseñanza.

Dios mío, pienso, ¡están intentando atontar el curriculum aún más! ¿Por qué no dar a cucharadas todo a los estudiantes? Dejemos también que los TA hagan los exámenes en lugar de ellos, así nadie se cambiará a unos Estudios Americanos. ¿Cómo se supone que nadie pueda aprender algo si el curriculum ha sido diseñado cuidadosamente para hacer todo más fácil de lo que ya es? Parece existir un comité especial (PDF) dedicado a averiguar un sencillo subconjunto de Java que pueda enseñarse a los estudiantes, generando documentación simplificada que esconda con cuidado toda esa basura de EJB/J2EE fuera del alcance de sus tiernas mentes, de forma que no tengan que preocupar a sus pequeñas cabezas con clases que no necesitan para resolver los problemas más simples de informática.

La interpretación más comprensiva de por qué los departamentos de informática son tan entusiastas con atontar las clases es que les deja más tiempo para enseñar conceptos reales de informática si no tienen que gastar dos clases enteras en aclarar a los estudiantes la diferencia entre, digamos, un int y un Integer en Java. Bien, si es ése el caso, 6.001 tiene la respuesta perfecta: Scheme, un lenguaje para la enseñanza, tan simple que todo el lenguaje puede enseñarse y despejar a los estudiantes en cerca de diez minutos; entonces se puede dedicar el resto del semestre al punto fijo.

Bah, vuelvo a los unos y los ceros