Sobre los mensajes de error de los compiladores V. Javier Traver Dep. Lenguajes y Sistemas Informáticos Universitat Jaume I, Castellón, Spain vtraver@uji.es Resumen. Pese a los esfuerzos que se realizan en proporcionar técnicas y herramientas que faciliten el complejo proceso de desarrollo de software, existe un aspecto que parece olvidado: los mensajes de los compiladores. Sin embargo, dichos mensajes constituyen el ingrediente fundamental para una efectiva interacción programador-compilador. Este artículo reflexiona sobre este descuidado tema, que afecta a todo tipo de programadores, pero de modo especial a programadores noveles (e.g., estudiantes de informática), cuyo aprendizaje de la programación puede verse obstaculizado por dichos mensajes. Analizamos algunos de estos mensajes para un compilador concreto, en el contexto de una asignatura de programación de una universidad española, y proponemos algunas medidas dirigidas a solucionar o reducir este problema. 1 Introducción Desde la ingeniería del software se han propuesto principios, técnicas, métodos, estrategias, y herramientas para dar soporte al complejo proceso de desarrollo de software. Paradójicamente, la atención se ha centrado en unas partes de este proceso, de modo que el programador sigue desasistido en la intelectualmente exigente tarea de la codificación. Posiblemente, esta falta de atención se deba al estereotipo, aún vigente, del programador como un «todo-terreno», que debe apañárselas con su código y lidiar como pueda con el compilador. Consideramos que esta situación no es deseable: el proceso de desarrollo de software, así como el del aprendizaje de la programación se pueden resentir seriamente. La disciplina HCI puede, sin duda, arrojar luz sobre este tema. Sin embargo, sus esfuerzos en el campo de la programación han girado en torno a temas como programación textual vs. visual; paradigmas procedimentales vs. orientadas a objetos; etc. [6]. Un trabajo con una preocupación similar se remonta a 1982 [4]. Por aquel entonces, algunas voces reconocían el escaso interés prestado por la comunidad HCI hacia los mensajes de error [1]. Aunque estos primeros trabajos se centraban en el problema general de estos mensajes, Shneiderman [5] documenta experimentos en los que mensajes de error de COBOL se modificaron para evaluar su influencia en los programadores. Un trabajo anterior [2] trataba sobre la adecuada comunicación compilador-programador. No deja de sorprender el hecho de que, a pesar de que han transcurrido tres décadas desde estos estudios, los mensajes de error en general, y de los compiladores en particular, siguen siendo poco usables. Una mirada a los avances 344 – Traver, V.J. e investigación en la tecnología de los compiladores nos revela una falta de preocupación, casi absoluta, hacia este tipo de cuestiones. Una interesante excepción es el trabajo de Jeffery [3]. 2 Un caso de estudio En el curso 2.002–03 prestamos atención a y recopilamos algunos de los mensajes de error que nuestros estudiantes de la asignatura Programación Avanzada (2º curso de Ingeniería Informática, Universidad Jaume I), se encontraron al elaborar sus programas en C++ con el compilador g++. Un análisis de las dificultades que supone comprender un mensaje y diagnosticar el correspondiente error del código fuente, nos sugiere clasificar los mensajes en varios tipos: Mensajes poco claros y poco específicos. Un ejemplo de este tipo de mensaje es: ANSI C++ forbids declaration 'ostream' with no type 'ostream' is neither function nor method; cannot be declared friend parse error before '&' El diagnóstico, no trivial para un programador novel, es que falta incluir el fichero de cabecera iostream. Pensamos que el compilador, idealmente, debería «afinar» más, siendo su mensaje más cercano al posible diagnóstico, de modo que el programador pueda rápidamente entender y arreglar el problema. De lo contrario, los mensajes suponen una importante distracción de la principal tarea. Mensajes confusos o engañosos. Aquí can't initialize friend function '<<' friend declaration not in class definition el problema estaba en que la palabra clave friend aparecía al definir la función, cuando sólo hay que ponerla al declararla. Sin embargo, la indicación del mensaje no sugiere para nada que éste sea el problema. Se habla de «inicializar», lo que puede despistar más que ayudar, y de «declaración», término que todavía no terminan de entender los estudiantes (lo confunden con «definición»). Mismo error lógico, diferentes mensajes. El diagnóstico de este otro mensaje: In method 'float SavingAccount::getInterestRate()': parse error before '{' era que faltaba cerrar con ‘}’ el cuerpo de la función precedente. Sin embargo, dependiendo de dónde falte este carácter (‘}’), los mensajes del compilador difieren sustancialmente. Esta falta de consistencia dificulta el que un programador novel elabore un buen modelo mental y le permita, en el futuro, dado un mensaje de error, predecir su diagnóstico. Otro problema es la falta de precisión en la localización del error. El compilador indica una línea del código, y los programadores tienden a mirar el código localmente, Sobre los mensajes de error de los compiladores – 345 en busca del error sintáctico/semántico. Sin embargo, en este caso el problema está bastante antes que la línea marcada como errónea, y como excepción, el texto de este mensaje podía ayudar, puesto que indicaba el nombre de la función. Desafortunadamente, el programador, sobre todo el novel, acostumbrado a la poca ayuda ofrecida por los mensajes de error, se habitúa a fijarse más en la posición del error que en el texto del mensaje. Mismo mensaje, muchos posibles errores lógicos. Un contexto concreto en que aparecía este mensaje parse error before , era debido a que se ponía el tipo de los argumentos que se pasaban al constructor de la clase base, en la lista de inicialización del constructor de la clase derivada, cuando, al tratarse de una llamada a una función, debía pasarse sólo los parámetros (no se trataba de una declaración). Además de la nula ayuda que ofrece el mensaje en este contexto, el agravante está en que multitud de errores lógicos pueden estar asociados al mismo mensaje. Ello dificulta el aprendizaje, porque no es posible generalizar y aprovechar el diagnóstico hecho en un caso para reutilizarlo cuando vuelva a ocurrir este mismo mensaje. 3 Posibles soluciones La solución ideal es que los mensajes de error de los compiladores sigan los criterios de usabilidad comunmente establecidos. Ello beneficiará a todos los programadores, no sólo a los noveles. A partir del análisis de estos y otros errores (más detalles en [6]), sugerimos como criterios de diseño de mensajes de error de los compiladores: (i) claridad y brevedad; (ii) univocidad entre mensajes y diagnósticos; (iii) localidad del error; (iv) adecuada redacción y tono; (v) ayuda extensible; (vi) consistencia; y (vii) apropiado diseño visual. No es difícil apreciar cuáles y cuántas de estas deseables propiedades se incumplen en los ejemplos vistos arriba. No obstante, las dificultades tecnológicas pueden hacer difícil, hoy en día, que los mensajes de los compiladores se acerquen al diagnóstico que necesita el programador. Si bien esta dificultad no debe hacer desistir del intento, y esfuerzos como [3] son muy loables, de momento sólo parecen viables soluciones alternativas que, en [6], denominamos Computer-Aided Compiler Errors Diagnostic (CACED). Sugerimos dos posibles enfoques CACED [6]: Programmer Driven (PD) y Compiler-Writer Driven (CWD), que se resumen y comparan, respecto a diferentes criterios, en la Tabla 1. Obviamente, la mejor herramienta CACED tendría los mejores aspectos de cada enfoque. En tales condiciones, el autor de la herramienta podría proporcionar un conjunto básico de diagnósticos en el momento de su construcción pero, además, durante el uso, cada usuario (programador) podría cambiar los mensajes de los diagnósticos para adaptarlos a sus peculiaridades, necesidades y conocimientos, así como editar el conjunto de diagnósticos, de modo que éste se vaya enriqueciendo progresivamente, al ritmo que el programador aprende y adquiere experiencia. 346 – Traver, V.J. Tabla 1: Características de las herramientas PD (Programmer Driven) y CWD (CompilerWriter Driven) CACED (Computer-Aided Compiler Error Diagnostic) Criterio Momento de creación Esfuerzo de crear los diagnósticos Significatividad de los diagnósticos Relación beneficio/coste Crecimiento del sistema Adaptación del sistema CWD Construcción Autor Comprometido Alta No posible No posible PD Uso Programador Garantizado Baja (se reinventa la rueda) Cuando se necesita Personalizable/adaptable 4 Conclusiones Los mensajes de error de los compiladores afectan al aprendizaje de la programación y al proceso de desarrollo de software a nivel profesional. Sin embargo, poco se ha investigado en intentar mejorar este fundamental aspecto de la interacción programador-compilador. Hemos analizado brevemente unos mensajes de error de un compilador concreto en un contexto específico de enseñanza-aprendizaje de la programación. Se han sugerido posibles soluciones, a corto y largo plazo, ante esta falta de apoyo a programadores noveles y avanzados. En el informe técnico [6] se expone con mayor nivel de detalle el contenido de este artículo. Este trabajo, hasta ahora de carácter más teórico, puede completarse mediante estudios de usabilidad con estudiantes y/o programadores, así como diseñando, implementando y evaluando herramientas que repercutan en una interacción programador-compilador más efectiva, productiva y agradable. Referencias 1. P. J. Brown. Error messages: the neglected area of the man/machine interface. Communications of the ACM, 26(4):246–249, Apr. 1983. 2. J. J. Horning. What the compiler should tell the user. In F. L. Bauer and J. Eickel, editors, Compiler construction: an advanced course, volume 21 of Lecture Notes in Computer Science, pages 525–548. Springer, 1976. 3. C. L. Jeffery. Generating LR syntax error messages from examples. ACM Trans. on Programming Languages and Systems, 25(5):631–640, Sept. 2003. 4. B. Shneiderman. Designing computer system messages. Communications of the ACM, 25(9):610–611, Sept. 1982. 5. B. Shneiderman. Designing the User Interface: Strategies for Effective Human-Computer Interaction. Addison Wesley, 1992. 6. V. J. Traver. On compiler error messages: what they say and what they mean. Technical report, Universitat Jaume I, Castellón, Spain, 2005.