¡Mándame un mensaje!
Tres Preguntas Acerca de Cada Error (Bug) Que Encuentres

Tom Van Vleck

Traducción libre por J. F. Díaz (jfdiaz98@hotmail.com) del artículo original Three Questions About Each Bug You Find.

¿A veces corriges un error, y luego encuentras otro relacionado al primero o a la forma que lo corregiste? Cuando corrijo un error, me hago tres preguntas para asegurarme que he pensado cuidadosamente acerca de su significado. Tu puedes usar esas preguntas para mejorar la productividad y la calidad cada vez que pienses que has encontrado y corregido un error.

La idea clave detrás de esas preguntas es que cada error es un síntoma de un proceso subyacente. Tienes que tratar esos síntomas, pero si todo lo que haces es tratar síntomas, continuarás viendo más síntomas por siempre. Necesitas encontrar qué proceso produjo el error y cambiar el proceso. El proceso subyacente que causó tu error es probablemente no aleatorio y puede ser controlado, una vez que identificas qué sucedió y qué provocó que sucediera.

Antes de que hagas las tres preguntas, necesitas dominar tu resistencia natural de observar cuidadosamente al error. Mira el código y explica qué salió mal. Inicia con los hechos observables y trabaja en retrospección, preguntándote por qué repetidamente, hasta que puedas describir el patrón en el que subyace el error. A menudo, deberías hacer esto con un colega, debido a que al explicar lo que piensas que ocurrió te forzará a confrontar tus suposiciones acerca de para qué es el programa.

“Estalló porque el subíndice J estaba fuera de rango.”
“¿Por qué?”
“J era 10 pero el último subíndice del arreglo es 9.”
“¿Por qué?”
“J es una longitud de cadena, y el inicio del arreglo es 0, así que el último carácter en una cadena de longitud 1 es el índice 0.”


Busca sorpresas adicionales en la situación al momento en que el error fue encontrado. Chequea variables claves del programa al momento de la falla, para ver si puedes explicar sus valores.

“¿Por qué es nulo el nombre?”
“¿Por qué estaba tratando de mostrar un mensaje de error de todos modo?”


Mantén anotaciones de lo que hiciste y qué sucedió. Necesitas saber realmente qué está sucediendo, y esto significa mantener mediciones y un registro histórico.

Cuando se hayan dado esos pasos, estás listo para la primer pregunta.

1. ¿Está este error también en alguna otra parte?
Observa otros lugares en el código donde se aplica el mismo patrón. Varía el patrón sistemáticamente para buscar errores similares.

“¿Dónde más uso una longitud como subíndice?”
“¿Todos mis arreglos tienen el mismo inicio de arreglo?”
“¿Qué ocurriría en el caso de una longitud de cadena cero?”


Intenta describir la regla local que debería ser cierta en esta sección del código, pero que el error desobedeció; tu búsqueda de esta invariante[1] te ayudará a ver otros errores potenciales.

“El desplazamiento inicial más la longitud, menos 1, es el subíndice final... a menos que la longitud sea cero.”

Es más productivo corregir varios errores por cada uno que encuentres. Intentar describir los errores en términos generales también eleva tu nivel de comprensión de lo que el programa está haciendo y ayuda a evitar la introducción de más errores mientras programas.

2. ¿Qué otro error está escondido detrás de este?
Una vez que hallaste cómo corregir el error, necesitas imaginar qué sucederá una vez que lo corregiste. La sentencia que sigue a la que fallaba puede tener un error en ella también, pero el programa nunca ha llegado hasta allí antes: o algún otro código puede ser introducido por primera vez como un resultado de tu corrección. Echa un vistazo a esas sentencias no probadas y busca errores en ellas.

“¿Funcionaría esta sentencia siguiente?”

Mientras estás pensando sobre el control de flujo es un buen momento para preguntarte si hay otras partes no alcanzadas del programa.

“¿Hay combinaciones de funcionalidades que nunca he probado?”

No toma mucho trabajo instrumentar un programa de tal forma que puedas chequear sus distintas partes mientras las ejecutas; y a menudo es sorprendente cuánto de un programa no funciona del todo después de que el constructor dijo que ha sido probado.

“¿Puedo hacer que todos los mensajes de error se muestren en las pruebas?”

Cuidado con hacer un cambio en un lugar que provoque un error en alguna otra parte. Un cambio local a alguna variable puede violar las suposiciones hechas más adelante en la ejecución.

“Si yo sustraigo uno de J, la sentencia move luego intentará mover –1 caracteres cuando la longitud de cadena es 0.”

Si ya has hecho un montón de cambios al programa, considera cuidadosamente si agregar otra corrección local es lo correcto por hacer, o si es tiempo para rediseñar y reimplementar.

3. ¿Qué debería hacer para prevenir errores como este?
Pregúntate cómo puedes cambiar tus mecanismos para hacer este tipo de errores imposible por definición. Al cambiar los métodos o herramientas, es posible eliminar completamente toda una clase de fallas en lugar de eliminar los errores uno por uno.

Empieza por preguntar cuándo fue introducido el error: ¿cuándo en el ciclo de vida del desarrollo pudo haber sido prevenido?

“El diseño está bien; introduje el error en la codificación.”

Examina la razón para que ocurriera el error en detalle. Piensa acerca del proceso que se estaba llevando a cabo al momento en que se introdujo el error, y pregunta cómo podría ser cambiado para prevenir el error.

“Separar los tipos de datos para desplazamiento y longitud hubiese atrapado este error en tiempo de compilación.”
“Cada elemento de texto pudo ser mostrado con una macro la cual esconde los cálculos de subíndices. Luego yo puedo resolver esto sólo una vez.”


No te des por satisfecho con respuestas locuaces. Supón que tu explicación para un error es, “Lo olvidé.” ¿Cómo puede cambiarse el proceso de tal manera que no necesites recordar? El lenguaje puede ser cambiado de tal forma que el detalle que omitiste esté completamente oculto, o tu omisión sea detectada y provoque un diagnóstico del compilador. Podrías usar un preprocesador del lenguaje para este dominio del problema, o una herramienta de edición ingeniosa la cual complete por defecto, chequee errores, o provea pistas y documentación rápida. El error puede ser un síntoma de problemas de comunicación en el equipo de programación, o de conflictivas suposiciones de diseño las cuales necesitan discusión.

Considera la forma en que fue encontrado el error, y pregunta cómo podría ser encontrado antes. ¿Cómo la prueba podría ser más impermeable? ¿Podría las pruebas ser generadas automáticamente? ¿Podría agregarse un chequeo de código en línea de tal forma que atrape errores todo el tiempo?

“Debería intentar una cadena de longitud cero en mis unidades de prueba”
“Podría habilitar un cheque de subíndices y capturar esto más pronto.”


Aplicación de la Técnica
Hazte el hábito de hacer las tres preguntas cada vez que encuentres un error. Ni siquiera tienes que esperar que aparezca un error para usar las tres preguntas.

Durante la revisión del diseño y la implementación, cada comentario que recibas puede ser tratado con las tres preguntas. Los comentarios de revisión son el resultado de un proceso de comunicación subyacente que puedes mejorar. Si sientes que el comentario de un lector sobre una especificación está mal, por ejemplo, podrías preguntar que evitó que tu documentación no fuera comprendida, y cómo podrías comunicarte menor con el revisor.

Las inspecciones de diseño y de código[2] son poderosos medios de hallazgo de muchos errores. Puedes hacerte las tres preguntas en cada defecto descubierto en los procesos de inspección. Las primeras dos preguntas no revelarán muchos errores si el proceso de inspección es cuidadoso, pero la tercera pregunta puede ayudar a encontrar muchos formas de prevenir errores futuros.-

Reconocimientos: Estoy agradecido con los muchos amigos y colegas que me enseñaron esas lecciones y enriquecieron mi vida y trabajo. Jay O'Dell, Rick Berman, y Tom DeMarco contribuyeron con valiosas criticas y consejos en las versiones previas de este documento.

Referencias
[1] Hoare, C. A. R., Proof of a Program; FIND. Comm. ACM 14, 39-45, Jan 1971.
[2] Fagan, M. E. Inspecciones de Diseño y de Código para Reducir Errores en el Desarrollo de Programas. IBM Systems Journal 15(3), 1976.
Lecturas Relacionadas

La Importancia de la Prueba del Software

Escribimos software pésimo... ¡y con bugs!

Técnicas de Depuración

Ir al inicio de este artículo | Volver a Documentos Web
Ir a la Página Principal de NeoProgramadores


alojamiento web gratis
Otros servicios ofrecidos por HispaVista:
Inmobiliaria y Dominios
Consigue una página web gratis o un
alojamiento web profesional con Galeón