Última actualización 16 de agosto de 2023
En la dinámica actual y especialmente en ciudades con alto grado de urbanización, nuestras vidas literalmente dependen del software. Los sistemas y las aplicaciones (en sus diferentes presentaciones) forman parte de nuestro día a día y una porción significativa de nuestra labor productiva, social, personal y hasta familiar pasa cotidianamente (como información) a través de ellas.
La certeza del correcto funcionamiento del software es algo que generalmente damos por sentado; sin embargo, siendo el éste (todavía) producto de humanos, también está sujeto a errores los cuales pueden tener diferentes fuentes y muy diversos efectos, desde cálculos erróneos, funcionalidad inhabilitada, imposibilidad de guardar cambios, hasta fuga de información. Dependiendo del contexto, tales efectos pueden pasar desapercibidos o poner en riesgo la vida de las personas.
Por esta razón la gestión de defectos (estén atentos sobre una próxima publicación sobre este tema) es un proceso fundamental en el desarrollo de software. Una parte de dicha gestión consta de analizar el origen y causas del defecto (ver Análisis de Causa Raíz o RCA) para entender cómo se gestó, qué impacto tuvo, cuál fue el proceso para su solución y cómo se pueden reducir errores similares en el futuro.
En mi experiencia con proyectos de software de diversas industrias, arquitecturas, tecnologías, plataformas y magnitudes, he compilado y desarrollado una clasificación de defectos relativos a su origen que propicia las siguientes ventajas:
- Ecualiza los defectos: Agrupa los defectos por causas, independientemente de sus consecuencias o la magnitud de su impacto.
- Apoya en su priorización: permite realizar una comparativa de volúmenes entre categorías.
- Permite visualizar tendencias o patrones: por ejemplo, la segregación en categorías puede hacer más evidente el agrupamiento de defectos (defect clustering) en módulos y segmentos de código, en colecciones de datos o componentes de la arquitectura).
- Aprovecha las lecciones aprendidas: sirve como apoyo en el análisis de la ejecución de medidas generales tanto correctivas como preventivas, por ejemplo relacionadas con las mejores prácticas asociadas a la categoría o que hayan sido aplicadas con anterioridad en defectos de la misma categoría.
- Promueve procesos de mejora: sirve como base en la generación o derivación medidas correctivas o preventivas adicionales sobre una base probada y común.
- Democratiza la gestión de defectos: al considerar que los defectos se producen por la interacción de los miembros de un equipo y no solo de un rol particular.
Las categorías propuestas obedecen a tres premisas fundamentales:
- Atender a las causas del defecto y no a las consecuencias (causalidad)
- Generar el menor traslape posible entre las categorías (segregación)
- Procurar el agrupamiento de todos los defectos (universalidad)
Como veremos en la discusión posterior, en la práctica pueden ocurrir casos en los que sea difícil realizar clasificación del defecto; es principalmente por esta razón que la lista propuesta no pretende ser exhaustiva ni definitiva, sino servir como guía para que cada equipo desarrolle su propio esquema de modo que se ajuste al contexto y las condiciones de sus proyectos.
Categorías para la clasificación defectos
Defectos causados por datos: este tipo de defectos tiene su origen en la fuente donde se almacena la información para su extracción y posterior procesamiento y/o despliegue. Por ejemplo: datos almacenados en formato incorrecto (por ejemplo, para internacionalización) o con valores inapropiados, recursos digitales (imágenes, documentos, tipografías) erróneos o no disponibles, etc.
Defectos causados por lógica de programación: este tipo de defectos causan problemas en la funcionalidad del software relativos a una mala implementación del algoritmo, o el proceso que promueve dicha funcionalidad y generalmente están relacionados con la falta de análisis de los datos de entrada, una interpretación incorrecta del requerimiento (procesamiento de datos y la salida del proceso), errores en la codificación (falta de inicialización de variables, mal posicionamiento de elementos de inicio o fin de bloques de código, etc).
Defectos causados por procesos del SDLC: este tipo de defectos son causados por la falta de seguimiento (o la inexistente definición) de procesos relacionados con la generación y despliegue (deployment) del código del software; por ejemplo, el mal seguimiento de estándares de codificación, el despliegue faltante o incorrecto de elementos relacionados en conjunto (como código adicional, archivos de configuración, recursos asociados o cambios en el esquema de bases de datos), falta de ejecución de pruebas (unitarias, de humo o de regresión), etc.
Defectos causados por requerimientos incompletos: este tipo de defectos están relacionados con ambigüedades u omisiones en los requerimientos que dejan a la interpretación del lector aspectos importantes sobre la implementación y funcionalidad deseada. Por ejemplo en procesos ágiles es muy común que no se cumpla con el “Definition of Done” para las historias de usuario, y en equipos no muy maduros esto tiende a causar conflictos entre la interpretación de quien va a desarrollar la funcionalidad respecto a quien la va a probar. Una manera de identificar estos defectos es cuando en las discusiones entre los desarrolladores y los ingenieros de calidad aparecen frases como: “es que yo pensé”, “lo que yo había entendido es”, o “como no decía, asumí”.
Defectos causados por las herramientas o el ambiente del SDLC: hay ocasiones en los que un defecto surge aun cuando tanto el código como los datos son correctos y se siguieron los procesos de manera correcta. Muchos de ellos son causados por inconsistencias en los ambientes en los que se despliega el código debido a configuraciones erróneas, conflicto en versiones de software requerido, uso de herramientas no estandarizadas para el desarrollo o la promoción del código, etc.
Defectos Inválidos: esta categoría obedece a la necesidad de agrupar los “defectos defectuosos”, es decir, aquellos defectos que luego de una revisión terminaron siendo funcionalidad esperada o se descarta su atención por no obedecer a una especificación o inclusive por ser trivial en el contexto. En muchos casos estos defectos son eliminados de la bitácora; sin embargo, es importante mantenerlos como evidencia tanto del esfuerzo invertido por quien lo registró como de que los ingenieros de pruebas también cometen errores.
Defectos Removidos: esta categoría obedece a la necesidad de agrupar aquellos defectos que por cualquier causa no sean atendidos por el equipo que los generó. En muchas ocasiones los equipos pierden visibilidad del destino de este tipo de defectos por lo que es importante mantener evidencia de su existencia y (en la mayoría de los casos) procurar su seguimiento para la correcta actualización de su estado (por ejemplo si está todavía abierto, en progreso o cerrado)
Es cierto que pudiera pensarse (especialmente si comulga con la frase: “todo se reduce a las matemáticas”), que las categorías pudieran reducirse solo a “procesos, procesos, procesos”; sin embargo, en la práctica del desarrollo de software los procesos pueden llegar a ser muy complejos y esta visión reduccionista toma en cuenta que establecimiento y consecuente seguimiento de procesos previene fallas subsecuentes, de modo que si un defecto se presenta es por la falta de seguimiento o definición de un proceso, lo cual no necesariamente es cierto en todos los casos.
Existen diversos modelos de desarrollo de software que funcionan bajo la premisa de la definición exhaustiva de procesos, pero requieren que dichos procesos y el equipo en sí sean muy maduros. Por consecuencia, se esperaría que el número de defectos inyectados debería ser menor en proporción al número de los procesos definidos; sin embargo, no hay una relación comprobable. ¨Por otro lado, en el mundo ágil del desarrollo de software, la definición formal y total de procesos simplemente es inviable.
El contexto único de cada proyecto de software hace que la clasificación de un defecto dentro de una de las categorías propuestas pueda ser relativamente sencilla o muy compleja, tome como ejemplo el siguiente caso:
Imagine un escenario donde una página web tiene un error en un texto legal donde algunas palabras cuentan con símbolos no alfanuméricos. Al ser un texto relativamente estático, de primera instancia se puede pensar que es un defecto de contenido o relacionado con los datos pero al verificar el almacenamiento (o la fuente) de los datos de forma directa no se observan los símbolos mencionados.
Una investigación más profunda revela que el texto fue extraído desde la herramienta de gestión de requerimientos e insertada en el archivo de almacenamiento mediante un proceso de copiar y pegar (copy-paste); sin embargo, el programa de edición de textos utilizado para actualizar el archivo de almacenamiento del texto resultó incompatible con el formato UTF, por lo que el texto aparenta ser visualmente es correcto pero su representación binaria en el archivo donde se almacena causa la aparición de símbolos cuando el servidor de web extrae el texto para su inserción en la página.
Si existe una política definida para el equipo sobre el uso de herramientas para los procesos de extracción de texto, entonces el defecto sería causado por no seguir los procesos del SDLC; de lo contrario sería un defecto causado por las herramientas del SDLC y como medida de mitigación se establecería la política mencionada.
Es importante mencionar que existe otra gran variedad de defectos no funcionales (por ejemplo de seguridad, de rendimiento, de escalabilidad, estabilidad, etc.) que no se encentran contemplados en la clasificación actual pero que, siguiendo las premisas de la clasificación aquí propuesta, puede incorporar en la clasificación definida para su proyecto.
La dinámica del universo del desarrollo de software es en realidad más caótica e inexpugnable de lo que parece por lo que (para mí) cualquier elemento de guía o apoyo puede hacer la diferencia entre encallar o llegar a buen puerto.
Desarróllate, desarrollando!