jueves, 14 de junio de 2012

Programación Extrema

¿Sabían que el XP de "Windows XP" deriva de una metodología de desarrollo conocida como eXtreme Programming? Cuando lo escuché por primera vez me lo imaginé de una forma bastante graciosa, más al comenzar a leer sobre el tema, dado que esto de las metodologías ágiles, si bien tiene su costado serio y muy útil, también da pie para encuadrar como metodología cosas ridículas, o a veces simples cuestiones de sentido común, que no ameritan la denominación de una metodología si no es más que para parecer elegante hablando con ilegítima propiedad. En fin, no vengo a cuestionar ni a defender las metodologías ágiles, ni la programación extrema, ya dije que hay muy buenas y muy malos, y yo no soy particularmente especialista en esto, más allá de mi experiencia de programar durante años sin metodología para descubrir después que lo que hacía podía encuadrarse en alguna de estas, probablemente de las malas. Sólo traigo el título a colación porque planeo malinterpretar uno sus postulados fundamentales, que según wikipedia es:
"Programación en parejas: se recomienda que las tareas de desarrollo se lleven a cabo por dos personas en un mismo puesto. Se supone que la mayor calidad del código escrito de esta manera -el código es revisado y discutido mientras se escribe- es más importante que la posible pérdida de productividad inmediata."
Es obvio que apunta a dos programadores discutiendo los algoritmos e implementaciones, pero vamos a hacer el ejercicio de omitir la palabra "persona" de la definición. ¿Que tal un programador y un robot?... Si el robot va revisando lo que escribe el programador, haciendo pequeños cambios, marcando errores, sugiriendo algunas mejoras, o hasta escribiendo algo de código, ¿no cuenta como programación en pareja? Si esto contara, la cantidad de gente que aplica este postulado ascendería notablemente.

Mi idea es que el IDE hace las veces del robot que proponía arriba. Muchos IDEs modernos nos autocompletan tanto identificadores en el código como llaves, comillas, paréntesis, corchetes, etc. Por ejemplo, si abrimos un bucle lo cierran para nosotros, lo que además de ser cómodo (se supone, no siempre) nos evita un potencial error. Muchos IDEs nos marcan los verdaderos errores y warnings automágicamente mientras escribimos, como si fuera la correción ortográfica y gramatical de Word o de LibreOffice. Algunos warnings son simples, pero otros tienen un nivel digno del mejor analizador estático de código y muestran verdaderos problemas de lógica y no solo meras cuestiones de estilo. Muchos IDEs generan grandes bloques de código y hacen tareas de refactory para nosotros. Algunos nos presentan ayudas o referencias automáticamente mientras escribimos. Y así, pueden pensar varias pequeñas o grandes contribuciones que años atrás, cuando un editor de código era un block de notas con coloreado de sintaxis en el mejor de los casos y un botón para ejecutar, eran posibles sólamente teniendo un segundo programador a mano. Por ejemplo, cuantas veces uno escribe con un error, pero como relee el código pensando en lo que quiso decir le es casi imposible encontrarlo, mientras que a otro compañero le resulta evidente. Está claro que estas ayudas del IDE no me sirven para discutir la complejidad de un algoritmo, la elección de una estructura de datos, de una biblioteca, o para encontrar errores de lógica específicos del problema que estoy resolviendo; pero nadie puede negar el conjunto de herramientas de un IDE moderno se parece a un robot cada vez más inteligente.

En fin, más allá de la inquietud que me causó encontrar esta similitud mientras trataba de pensar en un título y una introducción para este post, la idea era hablar un poco de cómo incorporar algunas de estas cosas en PSeInt y/o ZinjaI. Ya comenté en un post anterior que los compiladores actualmente me facilitan y de forma cada vez más rápida marcar los errores en tiempo real. Mi problema ahora es ¿cual es la mejor forma de aprovecharlo desde la interfaz? Para empezar a experimentar tomé primero PSeInt, dado que ahí controlo de principio a fin toda la cadena de herramientas involucradas. Esto quiere decir que el "compilador" (en este caso intérprete) es mio y puedo adaptarlo a lo que se me antoje. Por ejemplo, para que la cosa funcione más o menos rápido quería evitar tener que mandar a analizar el código lanzando el intérprete sobre un archivo temporal a cada rato. Entonces, lo que hice fué agregarle un modo al verdadero intérprete, en el que queda eternamente esperando por código en su entrada estándar, y cuando recibe una instrucción especial lo analiza e imprime los errores con un formato ad hoc. El editor lanza este proceso en segundo plano sin que nadie se entere, y le va pasando por una tubería (pipe) el código que el usuario escribe. El intérprete es capaz de analizarlo y resetearse a la espera del siguiente bloque. De esta forma me evito tener que crear y destruir procesos, y me evito tener que escribir y leer archivos temporales también, ya que se comunican por simples tuberías.

Pero la pregunta clave es ¿cuando pedirle que analice el código parcial que tiene el programador en el editor? Por un lado, hay cuestiones de eficiencia. No puedo hacerlo a cada rato porque esto tendería a entretener mucho al procesador y entonces el editor se empezaría a sentir lento o pesado en PCs no tan modernas. Por otro lado, la palabra clave es "parcial". Si analizo mientras el programador o alumno escribe, entonces analizo cosas incompletas, y entonces le marco errores que no son errores realmente. Es decir, puedo llegar a marcar cosas como "Te falta cerrar el bucle Para", pero en realidad eso pasa porque todavía lo está escribiendo, no porque se olvidó de hacerlo. Entonces hay una linea entre útil y molesto que no se exáctamente donde va. Por ahora, lo que hago es lo que supongo que hace la mayoría, esperar X segundos después de que el usuario apreta una tecla, y si no volvió a apretar otra supongo que es porque el código se "estabilizó" y ya puedo analizarlo. Pero si espero mucho, voy a estar un buen rato marcando errores que ya fueron corregidos, o no marcando errores que ya fueron cometidos, y en PSeInt particularmente, por su caracter educativo, esto es menos tolerable que en otros editores. Un buen programador entiende estos mecanismos y sabe perfectamente cuales errores fueron marcados porque el IDE se apuró a parsear, y cuales tienen verdadera importancia. Un alumno que está aprendiendo puede que no, y puede que esto lo confunda en lugar de ayudarle.


Además, siguiendo con el tema de la interfaz, está claro que marcar el error implica subrayar con estilo viborita la instrucción incorrecta, pero ¿donde va el mensaje de error? Mi experiencia me dice que el alumno en general es haragán y no lee mucho a menos que aparezca un cartel grande y luminoso en medio de la pantalla. Entonces, estrategias como la que creo tenía eclipse para con java (hace mucho que no lo uso) de poner un punto en el margen y mostrar el error cuando se hace click sobre él no funcionarían en este caso. Por eso, por ahora muestro la versión abreviada del error automáticamente en un globo tipo tooltip cuando el usuario se para sobre la instrucción equivocada, pero tengo que pensar algo mejor.

Dado que el 90% de lo que programo es en C++, y el 90% del otro 10% son scripts de bash, hace mucho mucho que no uso en serio otros editores o IDEs que no sean ZinjaI o kate/mcedit. Por esto no tengo tanta familiaridad con cómo resulven el problema otros editores, pero ya trataré de investigar. De todas formas, como estas herramientas se usan en el aula, para alumnos que recién empiezan, los criterios serán algo diferentes como ya expliqué, especialmente para PSeInt. Por eso empecé a experimentar un poco con su interfaz, que es más simple y particular, de forma de hacerme de algunas ideas y experiencias para cuando lo haga en ZinjaI. En cuanto tenga algo de tiempo libre voy a terminar de probar estos cambios (tengo que pulir algunos detalles) y subir una primer versión de PSeInt con esta característica para ver que feedback obtengo de los usuarios, y qué ideas me aportan para mejorarlo.

No hay comentarios:

Publicar un comentario