archivo

Archivo de la etiqueta: calidad del software

Un esquema tradicional de la implantación del software podría ser el siguiente: 1) instalación en el entorno de integración, 2) Pruebas del sistema en el entorno de integración, 3) Instalación en un entorno de pruebas/preproducción, 4) Validación de el entorno pruebas/preproducción, 5) Instalación en producción.

Que sea tradicional no quiere decir que todos estén de acuerdo con él (y el esquema sea absolutamente distinto) o que sobre el mismo no haya modificaciones.

No entro a valorar si las instalaciones se realizan de forma automatizada o no, no es el objeto del artículo sino de las pruebas o validaciones. Tampoco entro en si se deben realizar pruebas unitarias o automatizadas de mayor nivel, ya que me quiero centrar más en las pruebas de carácter manual que realiza el equipo de testing (si existe) y/o los usuarios.

¿Se debe probar antes de entregar? Por supuesto que los desarrolladores deben hacerlo porque pese a se prueben secciones del sistema durante el desarrollo, es necesario hacer un testing final que afecte al conjunto de funcionalidades entregadas y hacer pruebas de regresión.

¿Debe probar el usuario? Es cierto que se requiere que los usuarios tengan tiempo para realizar esta tarea y en muchos casos, cuando los cambios son significativos y la aplicación compleja, el esfuerzo necesario es importante. Yo soy partidario de que los usuarios prueben en el entorno de integración sobre todo si el impacto funcional del desarrollo es importante (y/o la criticidad del cambio lo aconseja) y si los desarrolladores no tienen un control funcional lo suficientemente sólido.

Otro factor a tener en cuenta es el tiempo medio que se suele tardar desde que se entrega hasta que el producto llega a producción, teniendo en cuenta los posibles rechazos que puede haber en ese proceso.

En cualquier caso, como suelo decir, no se trata de aplicar necesariamente una política general a todos los proyectos sino de realmente analizar las características del sistema (es muy importante tener en cuenta su criticidad), de los cambios realizados, de los usuarios, etc… lo que pasa es que a veces por buscar una armonización de las tareas de testing se suelen establecer una normativa común (que puede admitir o no excepciones motivadas).

También es importante recordar que normalmente el coste de corrección de una incidencia suele ser proporcional al tiempo que ha pasado desde que se ha incorporado al código.

La calidad es el cumplimiento de las expectativas del usuario teniendo en cuenta que además:

– Una deuda técnica acorde al contexto en el que se ha desarrollado.

– Una tasa de errores y un grado de acabado de los requisitos no funcionales como por ejemplo rendimiento y seguridad en función de las características del producto que se ha desarrollado.

¿Y la documentación? La que requiera el proyecto y el posterior mantenimiento/uso del producto, ni más, ni menos.

Si la calidad se centra en el proceso y no en el producto, nos encontramos con esta situación (es posible que difieras con mi definición de calidad del software pero lo más probable es que esté centrada en el producto y no en el proceso).

El origen del mismo es la creencia de que a través del proceso se consigue la calidad del producto, algo que en el desarrollo de software solo se conseguiría en proyectos donde las personas son algo secundario y no aportan valor, como pueden ser adaptaciones simples de productos ya existentes.

El problema lo tenemos cuando en cualquier circunstancia se quiere aplicar esta estrategia para asegurar la calidad del producto final, lo que resta flexibilidad al proceso de desarrollo, limitando la posibilidad de elegir la estrategia o enfoque más apropiado, mermando además, la capacidad de adaptación al cambio, algo que resulta esencial en el contexto de incertidumbre que rodea al desarrollo de software.

Si se fija al final del sprint una demo o una entrega es necesario dedicar tiempo al testing cuando se hayan finalizado las tareas fijadas en la iteración (previamente los mismos desarrolladores han debido probar el código que han hecho y si hay equipo de testing han debido colaborar en esas tareas conforme se va trabajando) además de otras tareas como puede ser la propia preparación de la entrega (si hay paso a producción o si la instalación en un entorno de demo lo hace un equipo distinto).

Esto quiere decir que la fecha final de los trabajos de desarrollo en la iteración debe ser anterior a la fecha de finalización del sprint. Otra posibilidad es considerar esas tareas de testing como una actividad más dentro de la pila de sprint. El tiempo que se debe dedicar a esta actividad no debe ser exclusivamente el necesario para hacer el testing sino que hay que prever un tiempo para corregir incidencias, ese tiempo lo determinará el equipo en función de la deuda técnica, de la complejidad de las funcionalidades desarrolladas en el sprint y del estado actual del equipo de proyecto (si ha habido cambios en el equipo existirán más posibilidades de que se hayan producido incidencias).

En cualquiera de los dos casos se reduce la cantidad de trabajo que se puede abordar en la iteración pero siempre será mejor eso que entregar software deficiente porque supondrá una resistencia para la próxima (o próximas) iteraciones.

Aunque resulte paradójico, la agenda es una de las principales causantes de la pérdida de control del proyecto porque en el momento en que se rompen sus premisas: estabilidad de las especificaciones, del contexto y acierto en las predicciones de coste y plazos y no se trata esta situación de manera natural ajustando la misma a la nueva realidad, estaremos trabajando en una condiciones fundamentadas en unas hipótesis erróneas y de esa situación no se puede esperar nada bueno.

La crisis del software se asoció al no cumplimiento de las agendas porque efectivamente los proyectos no cumplían objetivos de costes, plazos, alcance y calidad y a partir de ahí se constituyó la gestión predictiva de proyectos generando con las experiencias pasadas y con el paso del tiempo todo un cuerpo de conocimiento.

Precisamente este problema es el que sufren los desarrollos que siguen el enfoque clásico pero perfectamente son extrapolables a enfoques pretendidamente ágiles si los mismos están condicionados por agendas rígidas (digo pretendidamente porque agenda rígida y agilidad son conceptos contrapuestos).

Como es lógico, se mejoraron los resultados del pasado porque hay que tener en cuenta que se pasó del caos a un cierto orden, pero seguían sin ser satisfactorios a lo que había que sumar el desgaste que tiene este tipo de gestión entre todas las partes implicadas en el proyecto.

El culto a la agenda no es la solución porque pretende estabilidad y predicción en un contexto de incertidumbre que es inherente al desarrollo de software. Por eso, el centro no debe ser el triángulo de hierro sino el valor del producto de manera que costes, plazos y alcances supongan referencias y no límites.

La gestión de la capacidad, velocidad o carga de trabajo del equipo resulta esencial. Uno de los factores que más influyen en la pérdida de control es precisamente el intento de cumplir agendas imposibles.

Con mucho esfuerzo, siempre y cuando, exista posibilidad material de cumplir unos plazos, se pueden llegar a ofrecer unos resultados, pero, ¿a costa de qué?, ¿a costa de quién? Del producto y del equipo, ya que probablemente el sistema resultante tenga funcionalidades que no estén bien rematadas, tenga incorrecciones funcionales, numerosos bugs y la factura técnica sea francamente mejorable, a lo que hay que añadir el desgaste de las personas debido a la presión y al overtime.

Esto impacta en la entrega pero también en lo que queda de proyecto porque será necesario dedicar esfuerzo a “barrer” o “pulir” lo que fue mal mientras se está trabajando en lo nuevo.

Si no se ha reajustado la capacidad de trabajo asumible por el equipo, seguirá desbordado y lo más probable es que no cumpla con la mayoría de los compromisos y los que cumpla presenten deficiencias similares a los de la anterior entrega y se sigan acumulando flecos pendientes. Como una bola de nieve esto irá a más y más durante el transcurso del proyecto y si además se acumulan modificaciones funcionales serias sobre elementos ya desarrollados o hay cambios sensibles en el contexto del proyecto, se volverá absolutamente inmanejable.

Incluso con la intención de ajustar el trabajo a la capacidad del equipo podemos caer en la situación descrita si nos equivocamos a la hora de hacer ese ajuste, si bien, es posible a corto/medio plazo volver a una situación más equilibrada ya que gracias a este enfoque tendremos en cuenta ese esfuerzo de más que vamos a necesitar en cada iteración para lograr ese objetivo.

Comenta Bertrand Meyer que: “El único gran enemigo de fiabilidad (y tal vez de la calidad del software en general) es la complejidad”, y tiene gran parte de razón.

La complejidad en sus dos vertientes: incluir funcionalidades no necesarias (o hacer más complejas funcionalidades que sí son necesarias) y descuidar la arquitectura y construcción del software haciendo el software mucho más complicado de evolucionar (mayor esfuerzo y mayor probabilidad de errores).

Tenemos que aprender a ser pragmáticos, a dejar de construir la casa por el tejado, a querer rizar el rizo sin ni siquiera tener el producto funcionando y todo ello sin olvidar que si no se construye software de calidad estamos poniendo resistencia y frenos a la capacidad de adaptación y evolución del sistema.

Una solución más compleja no tiene por qué ser mejor, una solución con más funcionalidades no tiene por qué ser mejor y una solución que esté a lo último en tecnología no tiene por qué ser mejor. Lo de menos es más, no es tampoco ciencia exacta, pero la verdad es que funciona más veces de lo que creemos.

Si desarrollas una solución demasiado compleja, al final pasa como con los mandos a distancia, muchos botones, muchas funciones, pero al final no utilizas ni el 10% de ellas.

Por otro lado, añadir complejidad de manera sistemática sin tener el producto en producción supone prácticamente comprar toda la taquilla para un más que probable fracaso y con poco margen de maniobra posterior, ya que tendremos un software mucho más voluminoso que mantener (y con una mayor deuda técnica ) y habrá menos recursos económicos para hacerlo.

La definición del flujo de trabajo es algo que está abierto y es lógico que así sea porque cada equipo de trabajo y cada proyecto tiene sus peculiaridades.

Es frecuente encontrarnos con tableros que no tienen una fase para el testing y suele ser provocado porque se entiende que de manera implícita se encuentra en la fase de realización, construcción, desarrollo o como se quiera llamar.

Conociéndonos como nos conocemos los desarrolladores y nuestras prácticas habituales de no probar de manera adecuada los componentes que construimos es una buena idea incluir una fase de testing de manera explícita. Es cierto que no te asegura nada (hacer testing requiere de disciplina y buenas prácticas) pero el simple hecho de considerarse una actividad y visualizarse es algo que tiene mucha fuerza.

Por ese motivo, aunque creas que la inclusión de esa fase no aporta nada, prueba a hacerlo y tras un tiempo, trata de sacar conclusiones de manera objetiva a través del número de defectos que se hayan conseguido solventar antes de alcanzar producción en comparación con los valores que estuvieras obteniendo hasta ahora, a partir de ahí ya tendrás todos los datos necesarios para continuar con estas prácticas de manera general, en proyectos o sprints concretos o tomar la decisión de, como hasta ahora, no incluirla.