jueves, 31 de julio de 2014

La falacia del testing y algo más

Hoy quiero hablarles de una de las más aceptadas metodologías de desarrollo en el ámbito industrial (e incluso en el académico), aquella conocida como "test driven development". En este enfoque, lo primero en diseñarse son los casos de prueba que se desea que pase exitosamente un cierto programa y luego se implementa dicho programa de forma que satisfaga estas expectativas. El proceso puede ser iterativo, incorporando nuevos casos y posiblemente alterando la implementación realizada acorde a estos. Esta estrategia tiene una grandiosa ventaja: Permite al programador estar más claro desde el principio en lo que quiere implementar y las propiedades que cumple. Además le otorga un mecanismo para descubrir fallas en su implementación o en su intuición (siempre puede haber errores en la definición de casos de prueba también). Incluso hay muy buenas herramientas que permiten realizar pruebas unitarias con facilidad. Lo que es una lástima... es que está severamente limitado.

Ni tan exagerado. XD

¿Cómo que está limitado? El enfoque del "test driven development" está basado en un conjunto de prueba que sirve como heurística para la totalidad de las posibles entradas al sistema implementado. ¿Pero como asegurar que es una buena heurística? Un programa tan sencillo como un factorial tiene como dominio a la totalidad de los números enteros. Incluso restringiendo el mismo a un lenguaje de programación con enteros de 32 bits, existen 2^32 posibles entradas para el programa. Hacer 100 o hasta 1000 pruebas es totalmente insignificante. Para programas apenas un poco más complejos, las posibilidades se hacen completamente inmanejables. Claro, estas pruebas pueden diseñarse para englobar características de un gran conjunto de posibles entradas que, junto a la "buena intención" del programador, pueden dar una confianza aceptable en la calidad de la solución. ¿Pero cómo asegurar que se considera la totalidad de las opciones? Esto puede mejorarse incluso haciendo que el diseño de pruebas sea realizado por un equipo diferente e independiente del equipo implementador (de lo contrario, las pruebas estarán influenciadas por las propias expectativas de la solución ya planificada). Pero aún con todo esto, no parece ser suficiente.

Me imagino dos reacciones razonables al párrafo anterior: "Si, la estrategia tiene fallas, pero es mejor que nada" y la clásica "Bueno, ¿y tu que propones?" (no pude evitarlo, jajaja). La primera tiene toda la razón. Una estrategia que haga consciente al programador de lo que quiere implementar antes de empezar a echar código es mucho más responsable que la alternativa "dale play y si explota ahí vemos". Pero hay una opción que es mucho mejor y con eso aprovecho y respondo a la pregunta de la segunda reacción: el "contract driven development" o "design by contract" como lo llamó Bertrand Meyer (el pana que creó el lenguaje Eiffel). Sin embargo esto no es nuevo, viene de una larga línea de grandes pensadores de las ciencias de la computación en donde destacan personalidades como Edsger Dijkstra, Tony Hoare y hasta el mismísimo Alan Turing.

Este enfoque de diseño por contratos está basado en la filosofía de que todo programa puede especificarse formalmente. Esto es, las condiciones que se esperan al inicio, al final e invariantemente durante la ejecución del mismo pueden ser descritas por medio de alguna lógica formal. Esto se extiende a instrucciones, expresiones, tipos de datos, subrutinas, etc. Estas especificaciones o contratos se establecen antes de comenzar a implementar las soluciones y cumplen con dos objetivos importantes:
  • Los programadores tienen una idea clara de lo que deben implementar, las garantías con las que cuenta su programa (la forma del dominio) y lo que se espera del mismo al finalizar su ejecución. Esto guiará una implementación mucho más sólida y clara.
  • Una vez implementada la solución, la misma puede verificarse formalmente vía una demostración rigurosa que asegura, sin cabida a dudas, que la implementación cumple con lo establecido en su contrato.
¿Y que pasó con los lenguajes funcionales, que están en un nivel de abstracción tan alto que el programa mismo es su propio contrato? ¡Mejor aún! Tal nivel de abstracción es ideal para hacer pruebas simbólicas sobre los programas escritos directamente y finalmente tener la misma calidad y confianza (quizá hasta más que en un contexto imperativo). Más aún, pueden especificarse propiedades adicionales apoyadas por el sistema de tipos (la firma de una función es un contrato para la misma).

Sin embargo, esta solución tampoco es perfecta y tiene una buena cantidad de fallas significativas:
  • El contrato aún es tan bueno como la intuición de quien lo diseñó. Lo que se quiere puede estar mal especificado o, incluso, puede que no se esté claro siquiera cuál problema quiere resolverse realmente.
  • El tiempo dedicado para diseñar contratos y la posterior verificación de los mismos es mucho más grande que en otras estrategias de desarrollo. Los resultados tangibles pueden verse sustancialmente atrasados.
  • El contrato, similar a los casos de prueba, debe ser elaborado por un equipo independiente al implementador. La diferencia reside en que un contrato requiere de mucha más experiencia y formación que un caso de prueba, lo cual eleva las exigencias académicas y de personal necesarias para llevar a cabo un proyecto.
La primera falla es inevitable. Programar es una actividad humana y como tal está susceptible a tener fallas siempre. Lo que uno puede intentar es reducir estas fallas lo más posible y contenerlas de forma tal que los resultados sean suficientemente confiables. La segunda falla no es tanto una falla como más bien una inversión. Sí, un proyecto que pudiera haber tomado 3 meses, tomó quizá 6 a 8. ¡Pero se ahorraron los potenciales años reparando bugs, con una solución de calidad! La tercera falla es real y difícil; mucho más cuando una gran cantidad de programadores y profesionales de la computación están completamente desligados y desinformados en lo que concierne a métodos formales. Los que si los conocen están usualmente confinados a la academia o pueden llegar a ser muy costosos. Es mi opinión, y la de algunos otros que conozco, que todo profesional de la computación debería tener una formación sólida en métodos formales y hacerlos parte de sus herramientas de trabajo en su día a día. Eventualmente, especificar un contrato será natural para muchos, tanto como lo es diseñar casos de prueba actualmente y tendremos sistemas mucho más confiables, seguros y mantenibles.

¿Pero entonces todo hay que demostrarlo? No necesariamente. Idealmente, si, eso daría el 100% de confianza. Pero el tiempo es un factor innegable y a veces de verdad no alcanza para todo el rigor involucrado en una prueba completa. Existen herramientas de verificación que permiten hacer algunas demostraciones de forma automática. Estas herramientas no son generales, ya que el problema de hacer una correspondencia de una implementación con un contrato se sabe indecidible. Sin embargo, pueden ahorrar bastante tiempo y esfuerzo en un principio y dar ciertas garantías sobre el comportamiento de un programa.

Hay que tomar en cuenta que tampoco es la intención que se elimine el testing por completo. Las máquinas no se comportan exactamente igual a la teoría; hay fallas inherentes a la implementación física de sus componentes. Además, pruebas concernientes al desempeño, a la resistencia ante muchas consultas simultáneas e incluso a la aceptación de la solución son aún necesarias, pero se delegarían a un siguiente paso del desarrollo.

Esto era lo que quería compartir por ahora (otro post más gallo aún, jajaja). Esto de los métodos formales no sólo es una rama fascinante de la computación, sino una que creo necesaria conocer para ofrecer soluciones confiables y de calidad. Como siempre, cualquier opinión es más que bienvenida. ¡Hasta la próxima! :)

sábado, 26 de julio de 2014

Discretamente hablando: Haskell

Desde hace ya un tiempo he pensado que la enseñanza de las Matemáticas Discretas puede aprovechar muy positivamente usar un lenguaje funcional puro como Haskell. Claro, no se usaría a efectos de las demostraciones (quizá como notación, pero no más), pero si sería muy útil para mostrar conceptos y propiedades de diferentes construcciones interesantes. En particular, sería sencillo mostrar que una cierta colección de objetos admite alguna estructura algebraica como un monoide, un grupo, etc.

¡Alabado sea Haskell, todopoderoso!

Tradicionalmente, estas estructuras algebraicas se construyen a partir de un conjunto llamado "carrier". Es mi opinión que tal construcción sería mucho más clara y útil si se hiciera a partir de tipos. Esto es, el carrier sería un tipo y las operaciones serían funciones sobre este tipo. ¡La cláusula de operación cerrada desaparece! Ya no hace falta, pues la declaración de tipos no permite operaciones mal formadas.

Por ejemplo, se podría definir un monoide como una tupla (T, +, e), donde:
  •  + : T → T → T
  •  e : T
  • ∀ a, b, c : T (a + (b + c) = (a + b) + c)
  • ∀ a : T (a + e = a ∧ e + a = a)
Y no hizo falta mencionar que el operador (+) es cerrado, ya que es obvio por su tipo (creo que el uso funciones currificadas da más flexibilidad a la hora de continuar explicando los conceptos en un futuro).

A continuación les dejo un enlace a un programa en Haskell que escribí con los conceptos básicos de grupoide, semigrupo, monoide y grupo implementados como clases de tipos. Así como 3 ejemplos: enteros, Z4 (hecho a mano) y grupos de permutaciones.

Enlace: algebra.hs

Creo que quedó bastante bonito y claro, aunque quizá sea que ya estoy acostumbrado a leer Haskell, jajaja (que no es muy lejano a leer matemática). ¿Que opinan? Mi intención es que algún día se incorporen nociones así a la práctica de las materias Estructuras Discretas I, II y III de la USB (y equivalentes de otras universidades, si se animan). Esto, creo yo, cumpliría dos objetivos fundamentales:
  • El estudiante tendrá un mejor entendimiento de los conceptos al tener la oportunidad de jugar con ellos, equivocarse y contar con un entorno de compilación/ejecución que lo ayude y motive a mejorar.
  • A veces los conceptos en Matemáticas Discretas quedan muy en el aire, demostraciones secas sin ningún motivo aparente. Claro, forman el pensamiento, pero realmente es mucho más que eso. Muchas de las construcciones que se ven en estas materias son la base de estructuras de datos complejas y sumamente eficientes usadas actualmente. Ver la relación desde temprano puede ayudar a que se le vea el queso a la tostada y haya una mayor motivación por entender y aprender.

Y bueno, esto es lo que quería compartir por ahora. Otro post gallito como para que no digan, jajaja. Cualquier sugerencia u opinión es más que bienvenida. ¡Hasta una próxima entrada! :D

lunes, 14 de julio de 2014

Magíster en Ciencias de la Computación

¡Hoy fue el gran día! Finalmente, hoy a partir de las 10:00am. se celebró el acto de graduación en donde obtuve el tan anhelado título de Magíster en Ciencias de la Computación. ¡Que emoción! Me sentí igual de nervioso que en el acto cuando me dieron el título de Ingeniero (quizá hasta un poco más, jajaja). Mas ahora no cabe en mi la felicidad, el orgullo y la motivación para seguir aprendiendo y creciendo.

¡El título mesmoooh! :D

Fue un día repleto de emociones. Todo comenzó alrededor de las 4:30am., hora a la que nos tuvimos que levantar para llegar a tiempo al acto (a eso de las 7.30am.), y resulta que los de protocolo llegaron casi a las 9:00am., jajaja. En el acto me conseguí a muchísima gente que se graduaba también y que ahora puedo llamar colegas con orgullo y alegría. ¡Un privilegio compartir acto con tantos amigos y gente tan genial!

El acto estuvo muy bueno. El discurso de la graduando (Diosángeles) estuvo bastante bien, aunque quizá un poco lento y centrado en la experiencia IQ más que todo. Sin embargo, el mensaje se transmitió y realmente mereció dar ese discurso después todo lo que hizo por hacer posible esta graduación extraordinaria. El discurso del vicerrector lamentablemente dejó mucho que desear, ya que no tuvo casi nada que ver con el acto y además pintaba una escena muy negativa, incongruente con el ambiente de júbilo y celebración que debería ser propia de una acto de grado. Pero bueno, no todo puede ser perfecto, jajaja.

¡Que emoción cuando llamaron mi nombre! Y que orgullo escuchar tantas expresiones de apoyo de mi familia, amigos y colegas. ¡Un momento incomparable sin duda, fugaz pero eterno! Con orgullo aplaudí a todos los que vinieron después de mi (aunque debo confesar, que mucho más a los computistas, jajaja). Las canciones del orfeón estuvieron excelentes. El corte hacia el final de Barlovento y el arreglo armónico de la segunda canción quedaron buenísimos. Algo que me sorprendió era la poca cantidad de gente que cantaba el himno de la USB con el orfeón, aunque bueno, no siempre se oye ese himno, jeje. ¡Yo lo canté con orgullo! :D

Saliendo del acto, estuve un rato con mi familia y algunos amigos geniales hablando un rato y tomando fotos. Ahí fue que me dijeron que el porta-título tenía otra cosa (yo no la había visto). ¡Resulta que había una constancia de Mención Sobresaliente por el Trabajo de Grado! Que genial ver eso ahí, jajaja.

De ahí, a comer en Mokambo Caffe (en las Mercedes). Lo gracioso, es que habían otros graduandos ahí también. Pedimos ceviche y carpaccio de lomito como entrada, seguido de un risotto de cebollas gratinadas para mi (el resto de mi familia pidieron risottos de otros sabores, jajaja). ¡Que excelente estuvo! Y de poste una torta de queso, que estuvo simplemente mundial. Luego, fue tiempo de ir a visitar a la familia extendida (abuelos y tíos). Hicimos un brindis por el nuevo logro y pasamos un rato chévere (por supuesto, no podía faltar el "regaño disfrazado de felicitación" de todos los días con la familia indirecta de uno, pero la intención es buena que es lo que cuenta, jajaja).

Y bueno, después de un día fuerte pero genial (seguido de varios días de diligencias heavy metal), heme aquí escribiendo este post. ¡Estoy sumamente orgulloso y feliz! Y necesitaba compartirlo nuevamente por esta vía. ¡Gracias a todos los que me han acompañado, apoyado y alentado! Es un privilegio y un honor contar con su amistad y cariño. ¡Un abrazo gigante a todos! Será hasta una próxima entrada. :D

domingo, 6 de julio de 2014

Electiva Hipotética: Programación Cuántica

Siguiendo con la serie de electivas hipotéticas, continúo con un área que falta en nuestro departamento: la computación cuántica. Claro, los modelos físicos que intentan hacer realidad una computadora cuántica competen es a los físicos. Sin embargo, los algoritmos que han de ejecutarse sobre dichas máquinas hipotéticas y el razonamiento formal sobre los mismos compete a las ciencias de la computación.

¡Este tema me encanta!

El curso que propongo a continuación está inspirado en el curso "Quantum Mechanics and Quantum Computation" que fue ofrecido por Coursera en 2012. Seguramente le faltarán muchas cosas interesantes de las que podrían hablarse, por lo que cualquier comentario es siempre bienvenido. :)

Asignatura: Programación Cuántica 
Créditos:
Objetivo Principal: Introducir al estudiante a conceptos básicos de la mecánica cuántica, circuitos cuánticos y su uso en la implantación de algoritmos eficientes sobre máquinas cuánticas hipotéticas. Así mismo el razonamiento formal sobre estos algoritmos y de las clases de complejidad a las que pertenecen. 
Contenido:
  • Semana 1: Introducción al pensamiento cuántico. Axiomas de la mecánica cuántica.
  • Semana 2: Bases matemáticas: Números Complejos. Notación BraKet. Eigenvectores. Matrices Hermitianas. Productos de tensores.
  • Semana 3: Qubits. Entrelazamiento cuántico. Paradoja EPR. Experimento de Bell.
  • Semana 4: Compuertas cuánticas. Transformaciones unitarias.
  • Semana 5: Sistemas de N-qubits. Compuertas universales. Computación reversible.
  • Semana 6: Repaso y 1er parcial.
  • Semana 7: Algoritmo para muestreo de Fourier y Algoritmo de Simon.
  • Semana 8: Algoritmo de Shor y Algoritmo de Grover.
  • Semana 9: Clases de complejidad. BQP. Tesis de Church-Turing extendida.
  • Semana 10: Exposiciones
  • Semana 11: Exposiciones
  • Semana 12: Repaso y 2do parcial
(Nota: Las exposiciones serán sobre investigación actual en programación cuántica. Por ejemplo, en nuevos algoritmos que resuelven eficientemente otros problemas o lenguajes de programación cuánticos de alto nivel, etc.) 
Evaluación:
  • 4 Tareas - 5% cada una, para un total de 20%.
  • 1er parcial - 30%.
  • 2do parcial - 30%.
  • Exposición - 20%.

Y esto concluye la segunda de la tanda de electivas hipotéticas. Me encantaría poder investigar en esta área, ya que es algo diferente y sumamente interesante. Ya he leído algunos artículos y tesis doctorales en mi tiempo libre (que no es mucho, jajaja), pero me encantaría seguir trabajándolo. :)

sábado, 5 de julio de 2014

Electiva Hipotética: Introducción a la Programación Competitiva

Actualmente mucho departamentos de la USB han sufrido una fuga importante de personal docente, lo que ha supuesto una reducción significativa en la cantidad de cursos electivos que se ofrecen. ¿Por que? Las cargas docentes de los profesores restantes se cubren en materias obligatoria y básicas. Aún así, es cada vez más difícil cubrir todas las necesidades docentes en estas materias. Esto supone un buen grado de frustración a los profesores, ya que no les es posible dictar cursos en sus diferentes áreas de especialización y tener acceso a estudiantes interesados en dichas áreas para futura investigación y proyectos de grado.

En mi caso, tengo la fortuna de que mi principal área de especialización (lenguajes de programación) tiene tres materias obligatorias en el pensum de Ingeniería de la Computación en la USB:

  • Lenguajes de Programación I.
  • Laboratorio de Lenguajes de Programación.
  • Traductores e Interpretadores.

Por lo tanto, suelo estar asignado al menos a una de ellas por trimestre. ¡Son asignaturas que me encantan! Pero como todo, puede volverse monótono. En el caso de traductores, la he dado ya 2 veces como preparador, 3 veces como ayudante docente y 3 veces como profesor (con miras a una más, el trimestre que viene). Sería interesante poder trabajar algunas de las otras áreas que me interesan e incluso comenzar a investigar nuevas áreas. Con esto en mente, comenzaré una serie de artículos en este blog con "electivas hipotéticas". Esto es, con materias electivas que podrían comenzar a abrirse algún día cuando la USB vuelva a su antigua grandeza y haya mayor libertad para ser creativo.

Mundial ACM-ICPC 2010 en Harbin, China.
(Aquí participó un equipo de la USB)

De estas electivas hipotéticas plantearé un contenido y un plan de evaluación tentativos, de los cuales me encantaría tener feedback. ¿Quién sabe? Quizá se pueda abrir alguna de estas en un futuro no tan lejano (soñar no cuesta nada, jajaja). A continuación entonces, la primera de la serie de electivas hipotéticas.

Asignatura: Introducción a la Programación Competitiva
Créditos:
Objetivo principal: Familiarizar al estudiante con las destrezas técnicas necesarias para participar en competencias de programación al estilo ACM-ICPC
Contenido:
  • Semana 1: Introducción a las competencias de programación, sus herramientas y reglas. Medición general del nivel de los estudiantes previo al curso. Dinámica individual y grupal.
  • Semana 2: Problemas ad-hoc: Saber interpretar bien un enunciado, la especificación de entradas y salidas, restricciones de las mismas y tiempos límite.
  • Semana 3: Algoritmos voraces (greedy): ¿Como reconocerlos? Los peligros de confiar en una solución voraz. Criba de Eratóstenes. Búsqueda binaria. Potenciación logarítmica y Fibonacci.
  • Semana 4: Programación dinámica (básica): Los peligros de la fuerza bruta. Principio de optimalidad de Bellman. Top-Down vs. Bottom-Up.
  • Semana 5: Programación dinámica (avanzada): Inicialización virtual. Máscaras de bits.
  • Semana 6: 1ra competencia y discusión.
  • Semana 7: Grafos (básico): Búsqueda en grafos. Flood fill. Árboles cobertores. Componentes conexas.
  • Semana 8: Grafos (avanzado): Máximo flujo, mínimo corte y apareamiento bipartito.
  • Semana 9: Cadenas de caracteres: Suffix trees. Tries. KMP. Expresiones regulares.
  • Semana 10: Consultas en árboles. Segment trees. BIT. RMQ. LCA.
  • Semana 11: Algoritmos aproximados y heurísticas. Primalidad. Coloración de Grafos. Geometría y probabilidades.
  • Semana 12: 2da competencia y discusión.  
Evaluación:
  • 10 Tareas - 5% cada una, para un total de 50%.
  • 1ra Competencia - 20%.
  • 2da Competencia - 30%.
(Nota: Las competencias no se evaluarán por posición alcanzada, sino por la aplicación de los conocimientos adquiridos a los problemas presentados y dinámica de equipo. Sin embargo, habrán puntos adicionales para los ganadores de cada una.)

Y esto concluye la descripción de la primera electiva hipotética. Estoy seguro que me faltaron cosas por incluir, así que cualquier comentario es bienvenido. Hasta una próxima entrada. :D

viernes, 4 de julio de 2014

¡Se acabó el trimestre/semestre!

Finalmente, ha llegado el final de la semana 13 (o 21, si se cuenta desde el principio en Febrero). Ha sido un trimestre difícil en la USB, envuelto en una situación nada fácil para Venezuela, desde muchos puntos de vista. Sin embargo, poco a poco y con el mayor esfuerzo logramos dar buen final a este período académico.

Bueno, ni tanto... Pero más o menos. XD

Este trimestre estuve en dos cursos. En primer lugar, tuve a mi cargo un total de 61 estudiantes en la teoría de Lenguajes de Programación I. ¡Muy buen grupo! Dispuestos a aprender y trabajar. El primer parcial vio muy buenos resultados y el segundo fue un éxito sin precedentes (aún me siento orgulloso por el excelente desempeño de todos). El tercer parcial tuvo resultados no tan alentadores, lo cual debo admitir que supuso una gran frustración para mi. Después de todo, si todo un grupo sale mal es culpa del profesor, no del grupo. Pero varias personas me han convencido de que la situación de cansancio, de que estamos en pleno mundial de fútbol y de la falta de práctica de los temas que correspondían al laboratorio (que algunos tienen incluso años sin ver) fueron los principales motivos del empeoramiento de los resultados. Finalmente, casi un 80% del salón aprobó la materia y sin una pizca de regalo. ¡Todos se lo merecen y me siento sumamente orgulloso por eso!

Notas definitivas: Notas.pdf

El segundo curso en el que estuve fue en un Miniproyecto de Desarrollo de Software, en el que junto a Leonid Tineo, Rosseline Rodriguez, Soraya Carrasquel y David Coronado, servimos de guías y evaluadores a un grupo de tres estudiantes que desarrollaron una extensión de PostgreSQL para tratar con datos difusos de tipo 3 (así como consultas con ORDER BY y GROUP BY sobre los mismos). ¡Excelente trabajo y merecido 5 para todos!

En fin, fue un trimestre laaaargo y difícil, pero con excelentes resultados. Esto únicamente desde el punto de vista docente, que se agrega a otros eventos académicos importantes. Como... no sé... que me gradúo... por ejemplo. XD Eso y muchas otras cosas más.

Al finalizar el curso de lenguajes, decidí hacer una encuesta para ver como mejorar la experiencia del curso para futuras ocasiones. A continuación lo que mandé en el correo:

Hola a todos, 
   Ya se encuentran disponibles en la página las notas definitivas, con revisión y rezagados incluídos. Las notas que aparecen ahí ya fueron pasadas a DACE y... ¡con esto concluye oficialmente el curso de Lenguajes de Programación I! 
   Ante todo quiero agradecerles a todos por el empeño que pusieron en aprender y asimilar esta materia. No es una materia fácil y eso creo que ya nos consta bastante a todos, jejeje. Además el trimestre/semestre tampoco fue el más cómodo para cursarla, pero finalmente pudimos darle buen final. ¡Todo gracias a ustedes! Incluso para algunos de ustedes que no lograron aprobar, el empeño que pusieron y el conocimiento que adquirieron les servirá muchísimo para una próxima vez (incluso yo mismo reprobé lenguajes la primera vez que la vi. XD). Sigan todos así, con la iniciativa, curiosidad y empeño que mostraron este trimestre y les espera nada menos que la grandeza en sus futuras vidas profesionales. :) 
   También quería disculparme por todas las cosas malas que pudiera haber tenido el curso, asegurándoles que yo también aprendí mucho este trimestre y me gustaría seguir aprendiendo. Por esto, me gustaría pedirles en la medida de lo posible que me respondan a este correo las siguientes preguntas: 
   1) ¿Cuál fue tu impresión general de la materia?
   2) ¿Qué fue lo que se te hizo más dificil?
   3) ¿Qué cosas te ayudaron a aprender/avanzar con el material?
   4) ¿Qué cosas sientes que falten y que podrían haber ayudado a entender mejor la materia?
   5) ¿Qué recomendaciones tienes para una próxima vez que se abra la materia? 
   Es algo como una encuesta de opinión (pero más útil, jajaja). La idea es tomar sus recomendaciones y adaptar el curso como sea necesario para asegurar que los futuros estudiantes aprovechen la materia y puedan aprender más e incluso salir mejor. :) 
   Por ùltimo, me toca hacer publicidad. Muchos de los que están viendo la materia ya vieron Traductores. Para los que no, en traductores se muestra un lado más técnico de los lenguajes, concentrándose más que todo en la implementación de los mismos. La teoría de la materia presenta los conceptos y algoritmos abstractos que fundamentan todo esto, finalizando con el estudio formal de la computación misma. En este curso, el laboratorio trata de implementar un lenguaje de programación relativamente sencillo (usualmente un interprete). Seguido de Traductores y Lenguajes, lo que continúa es la Cadena de Lenguajes de Programación. En esta cadena unimos las interpretaciones de Lenguajes de Programación I y Traductores. ¡Les toca diseñar su propio lenguaje! Para implementarlo hace falta traductores, pero para diseñarlo bien hace falta lenguajes. Es una cadena sumamente interesante y donde se aprenden muchas técnicas que son útiles incluso más allá de la implementación de lenguajes. Si les gustó este curso y más aún, si les gustó/gustará traductores, les recomiendo muchísimo esa cadena. Mitos urbanos: ¿Es muy dificil? Realmente no tanto, hay cadenas más dificiles. ¿Lleva mucho trabajo? OHHHHH SI!!! XD Es el proyecto más grande y complejo que harán en la uni y posiblemente afuera de ella también, pero vale muchísimo la pena. :) 
   Con esto me despido, totalmente agradecido por compartir con ustedes esta experiencia y quedando totalmente a la orden (ya sea que quieran sólamente pasar a discutir algun tema interesante o incluso si buscan talleres de desarrollo o tesis en lenguajes de programación). *come to the dark side, we have cookies* :D 
Saludos a todos y felices vacaciones,
Ricardo
Recibí algunas respuestas sobre la encuesta (algunas hasta graciosas) que confluían en que lo que más ayudó fue las guías que se hicieron y las consultas. Las recomendaciones se centraron en hacer más guías para algunos de los otros temas que son difíciles de entender (como tipos de pasaje de parámetros, mezclado con orientación a objetos) e intentar de alguna forma compensar la falta de práctica de quienes vieron el lab hace tiempo (si bien sea insistiendo en que vuelvan a entrar o al menos practiquen con tiempo). ¡Gracias a todos los que me ayudaron son sus comentarios! Tomaré en cuenta sus consejos e intentaré hacerlo aún mejor una próxima ocasión que pueda dar la materia.

Y esto era lo que quería compartir por ahora. ¡Será hasta una próxima entrada! :D