Blog de Miguel Llopis

Tratado básico de Zoología Informática: Especies singulares de bugs y cómo combatirlos

Tradicionalmente, podríamos definir el término "bug" (de cuyo origen etimológico, sea leyenda urbana o realidad, ya hablamos hace tiempo por aquí) como un defecto, fallo o error del código de nuestra aplicación que deriva en un comportamiento anómalo de la misma, causando un resultado inesperado en nuestro programa.

Esta definición, de por sí bastante clara e intuitiva, es por otra parte demasiado genérica ya que bajo el término "bug" englobamos demasiadas mutaciones de los mismos. Partiendo de la base de que cada fragmento de código es singular y cada escenario diferente, lo cual da lugar a bugs de muy diversa índole, sí que es posible realizar una cierta taxonomía o clasificación de bugs en base a su comportamiento, o a la forma en que se manifiestan con mayor o menor frecuencia, e incluso de forma completamente impredecible.

Veamos algunos de estos tipos, así como los rasgos principales que los caracterizan y, por tanto, algunas estrategias de alto nivel que nos permitirán luchar contra ellos con ciertas garantías de éxito.

Bug atómico o Bohrbug

bicho

  Origen del término: Este bug básico debe su  nombre al Modelo Atómico de Bohr, y al igual que dicho modelo atómico, considera el bug como un elemento simple e indivisible, con características bien definidas y siempre deterministas.

  Características: El bug sencillo, claramente identificable y dependiente de una serie de factores estáticos. Este bug siempre se va a manifestar en la ejecución de nuestro programa si se dan las precondiciones o causas que lo propician.

  Posibles antídotos: Una forma efectiva de identificar estos bugs consiste en la realización de pruebas unitarias de acuerdo con la especificación de nuestro software. Es muy importante que estos bugs, de naturaleza sencilla, sean identificados lo antes posible en nuestros desarrollos, para evitar costes adicionales en su reparación. 

 

El bug estadístico

bug

Características: Bugs basados en pruebas estadísticas de nuestro software. A priori, son algo más complejos de identificar que los Bohrbugs, porque no se manifiestan en todas las ejecuciones de nuestro software. Sin embargo, la repetición cíclica de una misma prueba los pone de manifiesto, y a la larga comprobamos que responden a un patrón de comportamiento bien definido. Se trata de bugs del tipo: "Mi programa siempre falla en la N-esima invocación de cierto fragmento de código, a pesar de que las anteriores ejecuciones de este mismo método han funcionado perfectamente"

Posibles antídotos: La ejecución de pruebas estadísticas y pruebas de stress basadas en perfiles operacionales concretos de nuestras aplicaciones nos permiten detectarlos con relativa facilidad. Una vez detectados, la complejidad del escenario determinará la complejidad a la hora de identificar claramente las condiciones que los producen, y en base a ello, las medidas a tomar para mitigarlos.

 

El bug "efecto demo"

  Origen del término: Las primeras menciones a este término provienen del Alemán, el vocablo original es "Vorführeffekt" y significa efecto demo/presentación. Me gusta asociar este bug con el "adorable" Gizmo, nuestro programa puede ser igualmente adorable pero un pequeño descuido por nuestra parte puede dar lugar a la aparición de una criatura completamente diferente...

  Características: Nadie está libre de este tipo de bugs, y probablemente por vuestras mentes estén pasando ahora mismo situaciones célebres en la historia del software en las cuales estos bugs se han manifestado (jeje). En la aparición de este bug siempre influye el hecho de que el amigo Murphy nos visite o no en un determinado día... Este bug va siempre seguido de la manida excusa: "esto funcionaba ayer en casa". ¿Os suena?

  Posibles antídotos: Nunca te confíes. Si vas a dar una presentación en un determinado lugar, prueba siempre tus demos en este lugar. Si vas a emplear una determinada resolución de pantalla, asegúrate de que tu demo funciona con esta resolución. En general, verifica que todos los requerimientos de tu demo estarán disponibles en el momento en que la vayas a realizar (conexión a Internet, etc). Debes prestar especial atención a condiciones de "timeout" de tu aplicación o similares, las cuales pueden causar que incluso el bug se manifieste en un lugar en el que minutos antes de la presentación todo parecía funcionar a las mil maravillas. 

 

El bug de las Fases Lunares

Origen del término: A todos os resultará familiar la historia del hombre lobo... De igual forma, nuestro software puede adoptar comportamientos anómales en un momento determinado, una fecha determinada, etc.

Características: Se trata de un caso más o menos obvio de Bohrbug, pero que a su vez contiene un componente relacionado con cierto grado de arbitrariedad en nuestro programa.

Posibles antídotos: Prestemos especial atención a los comportamientos que se produzcan en nuestro software debido al uso de ciertos elementos, como por ejemplo funciones de fecha/hora.

 

El bug latente (Schroedinbug)

cartoon_bug

  Origen del término: El bug debe su nombre al famoso "experimento del gato de Schroedinger"

  Características: Nuestro programa funciona perfectamente durante semanas, meses, años... Llegado cierto día, un usuario detecta cierto bug en el sistema y, a partir de este momento, el resto de usuarios comienzan a experimentar el mismo fallo en cascada.

  Posibles antídotos: Este bug está especialmente relacionado con sistemas basados en máquinas de estados. El momento puntual en que se produce el primer fallo coincide con una transición no controlada dentro de dicha máquina de estados. El resto de fallos en cascada se producen por haber alcanzado lo que en la teoría de grafos se conoce como "estado de absorción" de nuestro grafo. Por tanto, deberemos poner especial atención en el diseño de estos sistemas. Esta especie de bug pone especialmente en relieve la importancia del software testing desde las primeras fases de especificación y diseño del sistema. Probablemente un análisis riguroso de las primeras aproximaciones del diseño nos habría permitido detectar estados no controlados del mismo, y redefinir dicho modelo de manera efectiva. Una detección tardía de este bug, como en la mayoría de casos, deriva en un incremento exponencial de los costes de reparación, lo cual repercutirá drásticamente en los costes de desarrollo de todo el proyecto.

 

El bug intrínseco o estructural (Mandelbug)

Origen del término: Este bug debe su nombre a Benoit Mandelbrot, matemático francés considerado el padre de la teoría de los fractales matemáticos. Dicha teoría, a grandes rasgos, proclama que un sistema puede descomponerse en pequeños fragmentos, los cuales son a su vez copias idénticas de menor tamaño que el sistema completo.

Características: Se trata de bugs que se manifiestan en escenarios de uso concretos de nuestro software, pero dichos escenarios no son más que "la punta del iceberg", puesto que son causa directa de fallos estructurales del diseño de nuestro software. El principal problema a la hora de resolver estos bugs radica en que, a menudo, las causas que producen estos bugs son (al igual que los fractales) una conjunción de elementos cuya percepción y diferenciación es demasiado compleja, con lo cual no es posible identificarlos claramente.

Posibles antídotos: Disponer de un diseño iterativo claramente definido acerca de nuestro sistema, y las relaciones y correspondencias entre los niveles de abstracción del mismo son herramientas que ayudarán a la hora de identificar las relaciones causa-efecto en estos casos. A pesar de que en muchas ocasiones consideramos suficientes e independientes los enfoques de diseño "top/down" y "bottom/up", conviene realizar ambos como mecanismo para una mejor compresión (y revisión) de las particularidades del sistema.

 

El bug indeterminista (Heisenbug)

bichos-03

  Origen del término: El bug indeterminista debe su nombre al físico Heisenberg y su famoso principio de Incertidumbre (no-determinismo).

  Características: Dado un determinado escenario de uso de nuestro software, las mismas acciones realizadas exactamente en el mismo orden producen una ejecución satisfactoria o un fallo. El análisis estático de nuestro software es claro, y la conclusión que de él extraemos es que todo debería funcionar a la perfección, sin embargo hay un determinado "duende" que juega con nuestro software (y nuestra paciencia) y hace aflorar un bug de manera arbitraria.

Se trata de ese tipo de bugs a los cuales dedicamos horas y horas de investigación, tazas y tazas de café y finalmente lo damos por imposible, o tal vez no... Todo dependerá de la tenacidad, perspicacia y capacidad de análisis metódico y ordenado del Ingeniero de Pruebas a la hora de diseñar el Plan de Pruebas ideal para cazar este bug tan escurridizo.

  Posibles antídotos: Generalmente este tipo de bugs se manifiestan en pruebas de integración o del sistema, siempre y cuando entendamos correctamente el significado de éstas. Consideramos dentro de este grupo a todas aquellas pruebas que contengan dependencias volátiles. Puedes encontrar una explicación acerca de estas dependencias volátiles en los materiales de mi última presentación en Gusenet, acerca de Windows Communication Foundation, en la cual analizamos diferentes tipos de pruebas sobre servicios. Como regla general, deberemos eliminar todo factor que introduzca indeterminismo en nuestro sistema: uso de funciones aleatorias (Math.Random), uso de librerías de terceros cuyo comportamiento no seamos capaces de controlar completamente, etc.

Dentro de esta última categoría de bugs, incluiremos también aquellas situaciones propias de entornos concurrentes (en las cuales el elemento causante de indeterminismo es la propia política del planificador de tareas de cada máquina, para cada ejecución), como pueden ser los interbloqueos (deadlocks), esperas ocupadas, colisiones en segmentos de memoria críticos, acceso exclusivo a recursos, etc.

Para esta última categoría, Microsoft Research está desarrollando una herramienta que permite analizar y simular de manera sistemática y determinista la planificación de procesos concurrentes. La herramienta en cuestión se denomina CHESS, y puedes encontrar información en la página web del proyecto, así como en el siguiente vídeo de Channel 9 con el equipo de desarrollo del proyecto, así como en esta sesión del PDC.

Si dispones de un par de horas para ver vídeos, te recomiendo invertirlas en aprender acerca de este interesante proyecto.

Posted: 15/12/2008 8:03 por Miguel LLopis | con 3 comment(s) |
Archivado en: ,,
Comparte este post:

Comentarios

Miguel LLopis ha opinado:

Buenas,

Independientemente de que sean o no de Microsoft, todas aquellas librerías de las que no podamos garantizar su correcto funcionamiento, deberán excluirse de nuestras pruebas unitarias.

Un caso especialmente destacable son aquellas librerías para las que disponemos de un número limitado de usos, nos interesará excluirlas también de estas pruebas unitarias y de pruebas de regresión, para aprovechar mejor su vida útil.

En última instancia, si de alguna librería no estás seguro si puedes/debes utilizarla en tus pruebas unitarias debido a su fiabilidad, sométela a sus propias pruebas unitarias para aquellos métodos que te interesen especialmente. No serán pruebas de caja blanca (en principio, parto de la premisa de que no dispones del código), pero si puedes emplear estrategias de prueba de caja negra y sus muchas variantes.

Un saludo,

Miguel

# December 17, 2008 9:44 PM

perci ha opinado:

cooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooool

# August 2, 2009 12:09 AM