Los Riesgos de las Universidades-Java

Este artículo de Joel Spolsky es, desde hace tiempo, uno de mis favoritos. Publicado originalmente en el año 2005, el paso del tiempo sólo lo ha hecho ganar rigor y actualidad.

Spolsky alerta sobre la creciente tendencia de muchas universidades a sobre-simplificar la currícula de las carreras de Ciencias de la Computación (con Java como «lenguaje insignia»), con el único objetivo de producir mayor cantidad de egresados y en menos tiempo. La consecuencia es directa: cada vez más abundan programadores que poco entienden de conceptos de programación (corrección, recursión, complejidad, paralelismo, entre tantos otros) y para los cuales los mecanismos «internos» de los sistemas informáticos (gestión de memoria, interacción con el sistema operativo, comunicación entre procesos, etc.) son completamente esotéricos.

El principal impulsor de este embrutecimiento es cierto sector de la llamada «Industria del Software» que requiere de mano de obra barata y de pobre formación, y empuja a las instituciones educativas a proveerles «recursos» tan rápido y en tanta cantidad como sea posible (ni qué decir de las instituciones educativas que ceden a esta presión).

Nadie está en contra de hacer la tarea del programador más simple, ni mucho menos de la evolución de los lenguajes y las metodologías de desarrollo de software. Lo que se reprocha aquí es la negación de la realidad como forma de evasión. Esto es: la necesidad de dotar a los programadores de ciertos conceptos, aún cuando esto provoque la deserción de quienes no puedan llegar a dominarlos (y mal que le pese al referido sector de la «Industria»).

Los Riesgos de las Universidades-Java

por Joel Spolsky
Jueves 29 de diciembre de 2005

Chicos perezosos.

¿Qué pasó con el trabajo duro?

Un seguro indicio de mi decadencia hacia la senilidad son mis continuas quejas y lamentos sobre «los chicos de hoy», y cómo ya no quieren o no pueden hacer cosas difíciles.

Cuando yo era un muchacho, aprendí a programar con tarjetas perforadas. En esos tiempos si cometías un error, no tenías ninguna de esas modernas funciones como la tecla «backspace» para corregirlo. Tenias que tirar la tarjeta y empezar todo de nuevo.

Cuando empecé a entrevistar programadores en 1991, les dejaba usar generalmente cualquier lenguaje que quisieran para resolver los problemas de programación que les planteaba. El 99% de las veces, ellos elegían C.

Ahora ellos tienden a elegir Java.

No me malinterpreten: no hay nada malo con Java como lenguaje de implementación.

Un momento, quiero rectificar eso último. No digo, en este artículo en particular, que haya algo de malo con Java como lenguaje de implementación. Hay un montón de cosas mal con Java, pero tendrán que esperar hasta otro artículo.

En cambio, lo que quiero decir es que Java no es, generalmente, un lenguaje de programación lo suficientemente difícil para que pueda ser usado para distinguir entre excelentes programadores y programadores mediocres. Puede ser un buen lenguaje para trabajar, pero ese no es el tema de hoy. Puedo ir incluso mas allá y decir que el hecho de que Java no sea lo suficientemente difícil es una característica, no un bug, pero que tiene ese problema.

Si puedo ser atrevido, diría que en mi humilde experiencia han sido dos las cosas tradicionalmente enseñadas en las universidades como parte de la carrera de Ciencias de la Computación (CS) las que mucha gente nunca llega realmente a comprender: punteros y recursión.

En aquellos tiempos lo normal era empezar la universidad con un curso de estructuras de datos, con listas enlazadas, tablas hash y, por qué no, con un uso intensivo de punteros. Esos cursos eran frecuentemente usados como filtros: eran tan difíciles que cualquiera que no pudiera soportar el desafío mental de un grado en CS se daría por vencido, lo que era bueno, porque si piensas que los punteros son difíciles, espera hasta intentar probar cosas en teoría de punto fijo.

Todos esos chicos que lo habían hecho muy bien en la secundaria escribiendo juegos de «pong» en BASIC para su Apple II, iban a la universidad, tomaban el curso CompSci 101, sobre estructuras de datos, y cuando llegaban al asunto de los punteros, sus cerebros estallaban completamente; y lo próximo de lo que tenías noticias es que estaban especializándose en Ciencias Políticas, porque la escuela de leyes parecía ser una mejor idea. He visto todo tipo de de índices de deserción en CS y usualmente están entre el 40% y el 70%. Las universidades tienden a ver esto como un derroche; yo creo que es sólo la poda necesaria de gente que no va a ser feliz o exitosa en una carrera de programación.

El otro curso difícil para muchos jóvenes estudiantes de CS era el curso donde aprendías programación funcional, incluyendo programación recursiva. MIT puso una barrera muy alta en esos cursos, creando un curso obligatorio (6.001) y un libro de texto (Estructura e Interpretación de Programas de Computadora de Abelson y Sussman, el cual era usado en docenas o quizás cientos de carreras de CS prestigiosas como el estándar de facto para la introducción a las Ciencias de la Computación. (Puedes, y deberías echarle una ojeada a la antigua versión de las clases en línea).

La dificultad de esos cursos es asombrosa. En la primera clase has aprendido casi todo Scheme, y ya has sido introducido a la función de punto fijo que toma otra función como parámetro. Cuando me esforzaba en pasar un curso similar, CSE121 en Penn, observaba cómo muchos sino la mayoría de los estudiantes simplemente no lo lograba. La materia era muy difícil. Inclusive escribí un largo email de lloriqueando a mi profesor diciendo que “simplemente no era justo”. Alguien en Penn debe haberme escuchado (o a alguno de los otros llorones), porque ese curso se dicta ahora con Java.

Desearía que no hubiesen escuchado.

Aquí radica el quid del debate. Años de lloriqueo de estudiantes perezosos como yo, combinados con quejas de la industria acerca de cuan pocos graduados en CS salen de las universidades americanas, han pagado su precio, y en la ultima década un gran numero de otrora perfectamente buenas universidades se han vuelto 100% Java. Esta de moda, a los reclutadores que usan “grep» parece gustarles, y, lo mejor de todo, no hay nada lo suficientemente difícil en Java como para filtrar aquellos programadores sin la parte del cerebro que entiende punteros y recursión. Así es que la deserción es menor, y los departamentos de ciencias de la computación tienen mas alumnos y mayores presupuestos y todo está bien.

Los afortunados chicos de esas Universidades-Java nunca van a toparse con raros fallos de segmentación tratando de implementar tablas hash basadas en punteros. Nunca se van a volver locos tratando de empaquetar cosas en bits. Nunca tendrán que ocupar sus cabezas en cómo en un lenguaje puramente funcional, el valor de una variable nunca cambia, y aun así, ¡cambia todo el tiempo! ¡Una paradoja!

Ellos no necesitan esa parte del cerebro para obtener un 4 en la materia.

¿Soy sólo uno de esos viejos cascarrabias anticuados, vanagloriándose acerca de cuán duro era sobrevivir a todas esas dificultades?

Rayos, en 1900, el Latín y el Griego eran asignaturas requeridas en la universidad, no porque sirvieran de algún propósito, sino porque de alguna manera eran considerados un requisito obvio de la gente educada. De cierta manera mi argumento no es diferente del argumento expuesto por la gente pro-Latín: “[El Latín] entrena tu mente. Entrena tu memoria. Desembrollar una sentencia en Latín es un excelente ejercicio del pensamiento, un verdadero acertijo intelectual y una buena introducción al pensamiento lógico”, escribe Scout Barrer. Pero ya no puedo encontrar una sola universidad que requiera Latín. ¿Son los punteros y la recursión el Latín y el Griego de las ciencias de la computación?

Ahora, admito que programar con punteros no es necesario en el 90% del código escrito en la actualidad, y de hecho es totalmente peligroso en el código de producción. OK. Está bien. Y que la programación funcional no es muy empleada en la práctica. De acuerdo.

Pero todavía sigue siendo importante para algunos de las tareas más excitantes en programación. Sin punteros, por ejemplo, nunca serías capaz de trabajar en el Kernel de Linux. No puedes entender una sola línea del código de Linux, o de hecho, de cualquier sistema operativo, sin realmente entender punteros.

Sin entender programación funcional, no podrás inventar MapReduce, el algoritmo que hace 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 su clase equivalente a 6.001 que los programas puramente funcionales no tienen efectos colaterales y por ende son trivialmente paralelizables. El simple hecho que Google inventara MapReduce, y no Microsoft, dice algo del por qué Microsoft está aun jugando a lograr que funcionen algunas características básicas de búsqueda, mientras Google se ha movido ya al siguiente problema: construir Skynet^H^H^H^H^H^H, la mayor supercomputadora masivamente paralela del mundo. Simplemente no creo que Microsoft entienda completamente cuan retrasados están en ese campo.

Pero mas allá de la importancia a simple vista de los punteros y la recursión, su valor real radica en que construir grandes sistemas requiere del tipo de flexibilidad mental que adquieres aprendiéndolos, y de la actitud mental que necesitas para no huir de los cursos en donde son enseñados. Punteros y recursión requieren cierta habilidad para razonar, para pensar en abstracciones, y más importante, para ver un problema en diversos niveles de abstracción simultáneamente. Por lo tanto, la habilidad para entender punteros y recursión esta directamente correlacionada con la habilidad de ser un gran programador.

No hay nada en grado académico 100% Java que realmente descarte a los estudiantes que carecen de la agilidad mental para tratar con esos conceptos. Como empleador, he visto que las Universidades 100% Java han empezado a producir en serie una buena cantidad de graduados quienes simplemente no son lo suficientemente listos para trabajar como programadores en nada mas sofisticado que «Sólo Otra Aplicación Contable en Java», aunque se las han arreglado para colarse a través de la (ahora simplificada) carrera. Esos estudiantes nunca sobrevivirían al 6.001 del MIT o al CS 323 en Yale y, francamente, esa es una razón por la cual, como empleador, un título en CS del MIT o Yale tiene más peso que uno de Duke, que recientemente se hizo 100%-Java, o de Penn, donde remplazaron Scheme y ML por Java tratando de enseñar la materia que casi nos mata a mis compañeros y a mi, CSE121. No es que no quiera contratar chicos listos de Duke o Penn, lo hago, es sólo que es mucho más difícil para mí darme cuenta de cuáles son. Yo estaba acostumbrado a decir que los chicos listos eran aquellos que podían desmenuzar un algoritmo recursivo en segundos, o implementar funciones de manipulación de listas enlazadas usando punteros tan rápido como podían escribir en la pizarra. Pero con graduado sde Universidades-Java, no puedo saber si padecen esos problemas a causa de haber sido mal educados o si los padecen porque realmente carecen de esa parte del cerebro que van a necesitar para ser buenos programadores en el trabajo. Paul Graham los llama «Blub Programmers«.

Ya es bastante malo que las Universidades-Java fallen en filtrar los chicos que nunca van a ser buenos programadores, algo que las universidades podrían justificablemente decir que no es su problema. Después de todo es la industria, o al menos los reclutadores-que-usan-grep, quien está pidiendo a gritos que se enseñe Java.

Pero las Universidades-Java fallan también en entrenar las mente de los chicos para ser hábiles, ágiles y lo suficientemente flexibles para lograr buen diseño de software (y no me refiero al “diseño” OO, donde gastas incontables horas acomodando tu jerarquía de objetos, o preocupándote de «problemas» superfluos como “tiene-un” vs. “es-un”). Necesitas entrenamiento para pensar en las cosas a varios niveles de abstracción simultáneamente, y ese tipo de pensamiento es exactamente lo que necesitas para diseñar excelentes arquitecturas de software.

Puedes estar preguntándote si la enseñanza de programación orientada a objetos (OOP) es un buen sustituto de los punteros y la recursión para el filtrado. La respuesta rápida: no. Sin debatir acerca de los meritos de la OOP, simplemente no es lo suficientemente difícil para filtrar a los programadores mediocres. OOP en las universidades consiste básicamente en memorizar un puñado de términos de vocabulario como “encapsulacion” y “herencia” y tomar exámenes del tipo «multiple-choice» acerca de las diferencias entre polimorfismo y sobrecarga. No más difícil que memorizar fechas destacadas y nombres en una clase de historia, la OOP tiene desafíos mentales inadecuados para espantar a los estudiantes de primer año. Cuando te enfrentas con un problema de OOP, tu programa aun funciona, sólo que es algo difícil de mantener. Supuestamente. Pero cuando te enfrentas a un problema con punteros, tu programa produce línea Fallo de segmentación y no tienes ni la menor idea de lo que está pasando, hasta que te paras, tomas una fuerte bocanada de aire y tratas de forzar tu mente a trabajar en dos diferentes niveles de abstracción simultáneamente.

Los reclutadores-que-usan-grep, de hecho, son ridiculizados aquí, y por un buen motivo. Nunca he conocido alguien que pueda usar Scheme, Haskell y punteros en C, que no pueda entender Java en dos días, y crear mejor código en Java que gente con cinco años de experiencia en Java. Pero trata de explicar eso al zombie de Recursos Humanos.

¿Pero que hay de la misión del compromiso con las CS de las facultades de CS? ¡Ellas no son escuelas vocacionales! No debería ser su trabajo entrenar gente para trabajar en la industria. Eso queda para los terciarios y los programas de capacitación del gobierno para trabajadores desplazados, dirán. Ellas se suponen que están para dar a los estudiantes las herramientas fundamentales para vivir sus vidas, no para prepararlos para sus primeras semanas de trabajo. ¿No es cierto?

Aun así, las CS son demostraciones (recursión), algoritmos (recursión), lenguajes (cálculo lambda), sistemas operativos (punteros), compiladores (cálculo lambda), y entonces la conclusión es que la Universidad-Java que no enseña C y no enseña Scheme, tampoco está enseñando realmente ciencias de la computación. Tan inútil como el concepto de currificación de funciones puede serle al mundo real, es un obvio prerrequisito para un graduado en CS. No puedo entender por qué los profesores en las comisiones curriculares de las facultades de CS han permitido que sus programas sean embrutecidos a tal punto que no sólo no pueden producir programadores operativos, sino que ya ni siquiera pueden producir graduados en CS que puedan obtener PhDs y puedan competir por sus puestos de trabajo. Oh, esperen. No importa. Quizás entienda.

Si volvemos en el tiempo y analizamos las discusiones que tomaron lugar en el mundo académico durante el “Gran Levantamiento Java”, encontraremos que la mayor preocupación fue que Java no era lo suficientemente simple para ser usado como un lenguaje de enseñanza.

Mi Dios, pensé, ¡están tratando de embrutecer la curricula aun mas! ¿Por que mejor no le llevamos la comida a la boca a los estudiantes? Dejemos que los ayudantes de cátedra den los exámenes por ellos también, entonces nadie se cambiara a Estudios Americanos. ¿Cómo se supone que alguien aprenderá algo si la curricula ha sido cuidadosamente diseñada para hacer todo más fácil de lo que ya es? Parece haber una comisión de trabajo (PDF) intentando idear un subconjunto simple de Java que pueda ser enseñado a estudiantes, produciendo documentación simplificada que esconde cuidadosamente toda esa basura EJB/J2EE de sus tiernas mentes, de manera tal que no tengan que preocupar sus cabecitas con otras clases que no necesiten para resolver sus aun más fáciles problemas de CS.

La interpretación mas compasiva de por qué las facultades CS son tan entusiastas en embrutecer sus clases es porque ello les dará más tiempo para enseñar verdaderos conceptos de CS, así no necesitaran dos clases enteras para esclarecer a los alumnos las diferencias entre, digamos, un int y un Integer en Java. Bueno pero si ese fuera el caso, 6.001 tiene la respuesta perfecta: Scheme, un lenguaje de enseñanza tan simple que el lenguaje entero puede enseñarse a estudiantes brillantes en unos 10 minutos; entonces puedes gastar el resto del semestre enseñando puntos fijos.

Fiu…

Voy a regresar a los unos y ceros.

(¿Te tocaron unos? ¡Bastardo suertudo! A nosotros nos tocaron todos ceros.)

 

Esta traducción está basada en la versión disponible en el Wiki de Joel Spolsky, corregida y adaptada por mí.

12 comentarios sobre “Los Riesgos de las Universidades-Java

  1. Es genial el artículo, ya lo recordaba de su época y coincido con que está de total actualidad.
    Hay gente que no adquiere LA VISION, y ni siquiera tratan de enseñarsela.

  2. Ahora me entero que las CS son sólo programación.

    ¿Dónde dejas la teoría de computabilidad? ¿A donde ha ido a parar la IA? Criptografía …¿eso qué es?

    A alguno le da la risa ver como quien denuncia el olvido de punteros no hace un breve recordatorio de lo importante que es la teoría, en todo, y que es lo que desde mi punto de vista separa la materia gris del polvo.

  3. Electec:

    Spolsky habla de la importancia de la teoría (fijate de lo que dice respecto de la recursión, puntos fijos, etc.). Claro que el artículo está orientado a los conceptos básicos indispensables, que tristemente están siendo dejados de lado en muchas universidades.

    La teoría de computabilidad es importantísima, pero es un tópico avanzado. La «Inteligencia Artificial» (¿existe eso?) y la Criptografía no me parecen indispensables.

    Es obvio que las Ciencias de la Computación son mucho más que punteros y recursión, pero me parece que estás equivocando el punto centrar del artículo.

  4. Hola Javier, sólo comentar que por supuesto estoy de acuerdo con muchísimas de las ideas del articulo, pero no estoy de acuerdo con el criterio que usa Spolsky para discernir entre chico listo/tonto.

    Lamentablemente mi universidad se convirtió en los últimos años en una Universidad-Java (hablo de Sevilla, España); tras una serie de misteriosas conferencias por parte de Sun; aunque tal vez la situación no sea tan desesperada, ya que existen asignaturas de SS.OO en las que entender muchos de los conceptos de los que se habla en el artículo son requisitos indispensables para poder seguir la asignatura.

    Por otro lado el tema de recursividad, si no te quieres enterar de lo que realmente es uno no se entera, y es que las asignaturas que tratan temas como este, conceptos como el de currificación, etc, son optativas. (Aunque si hay un par de asignaturas obligatorias en que el uso de haskell y lisp es obligatorio).

    Inteligencia Artificial… tal vez el nombre sea demasiado presuntuoso, pero si que creo que tiene la «independencia» suficiente como para poder considerarse una rama de las ciencias de la computación.

    Personalmente si que creo que conocimientos básicos de criptografía sean necesarios, y no solo eso, sino que el campo de la criptografía cuántica es muy interesante.

    Por otro lado un saludo, encantado de haber conocido tu blog.

  5. ése es precisamente el dilema de la educación, que se ha vuelto prescindible y, o el docente no se ha enterado o prefiere encerrarse en su castillo de la pureza o claudica sin asomo de vergüenza o cede para al menos sacar algún provecho.

    pero no hay necesidad del dilema, porque nadie está peleado con la técnica, las recetas y las necesidades particulares de la industria; al fin y al cabo, seguimos en una sociedad en particular aunque cerremos los ojos.

    ahora bien, me parece que el error de Spolsky es que supone que se trata de un problema de dificultad. las universidades se equivocan al aligerar el currículo, dice él, porque nos dejan sin herramientas para distinguir a los aptos de los ineptos. por tanto, hay que incrementar la dificultad.

    pero éste no es un asunto de grados ni de retos ni de filtros sino de fundamentos. la enseñanza no debe ser sólo instrumental (decir cómo y cuál es el camino óptimo) sino también integradora (cómo se relaciona esto con aquello, con lo anterior, con lo que sigue), multidimensional (cuántas capas tiene este conocimiento, qué categorías hay, cómo se influyen, afectar diversas áreas de mi vida), transformadora (ahora pienso, siento, veo diferente), propositiva (hay alternativas, se puede explorar).

    ejemplo:
    la industria quiere pintores que calculen la pintura que requieren; la universidad java les enseña potencias de dos, raíces cuadradas, reglas de 3, conversión de unidades.
    la universidad integral (por decirlo de algún modo) enseña lo mismo, pero dota el conocimiento de un contexto histórico (anécdotas de logros griegos resueltos de manera similar), científico (cómo le hace la calculadora, qué es un algoritmo, hay un orden), filosófico (¿ocurren las raíces cuadradas en la naturaleza? jiji, no es chiste; qué es un número, cómo es que un negativo se vuelve positivo con una potencia par; qué quiere decir que no hay raíces pares de números negativos).
    en otras palabras, la universidad integral no es que aumente la dificultad sino que te equipa para ver el cuadro completo, así, cuando salgas, si no hay trabajo de pintor, no hay problema, trabajarás vaciando cemento en los rascacielos porque tu preparación te permite intuir y arribar a potencias de 3 y raíces cúbicas.

  6. yo coincido totamente con Spolsky, yo soy estudiante todavia y estoy apenas en este mundo de la prgramacion, y si e notado mucha deficiencia en las bases fundamentales ya que no hay comprension, y no se profundisa y ssobre todo se adquieren bases muy solidas para que uno sepa lo que esta haciendo.

    Si es ahora muy facil cursas la universidad y es uan de als razones paro las que me aburre mucho. Se supone que la tecnologia es para ahcer cosas mucho mas complejas e interesantes. Pero como queremos ahcer eso si no comprendemos exactamente lo que se esta haciendo.
    Entre mas ocupemos el cerebro y pongamso retos mas facil sera resolver un problema de la indole que fues.
    Ahora hacen que el cerebro sea mas tontoy flojo y como resultado solo se crea una persona tonta.

  7. Me siento afortunado entonces que en mi universidad primero nos metieron a C y los punteros y las listas, pilas, etc. De verdad que en su momento fue muy difícil pero después pasamos a Java (que igual sólo nos enseñaron lo básico). Al menos puedo considerar tener un poco más la mente de buen programador.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *