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.

La tentación, muchas veces motivada por las circunstancias, es obviar la mejora de la factura técnica del producto, para centrarnos en corregir errores y en incrementar las funcionalidades.

El usuario siente la calidad del software con lo que ve: cumplimiento de sus expectativas de funcionamiento y buen rendimiento y disponibilidad, por eso pondrá resistencia a invertir tiempo en reducir la deuda técnica.

No debemos olvidar que desarrollamos para el usuario y él es quien tiene la última palabra, lo cual no quita que le expongamos la ventaja que tiene la realización de este tipo de tareas, como una inversión que permita no solo incrementar la capacidad de trabajo que puede abordar el equipo, sino además, reducir la posibilidad de efectos colaterales que provoquen errores cuando y donde menos los esperamos.

De serie, un desarrollador debe tener en cuenta estas prácticas y tenerlo en cuenta a la hora de definir su velocidad. El tiempo que se puede dedicar a esto puede ser prácticamente ilimitado porque todo es susceptible de ser mejorado, por ese motivo, ese tiempo de más sobre las buenas prácticas de programación cotidiana es el que se tiene que discutir con el cliente.

Comenta Mary Poppendieck: “La refactorización continua no es opcional. Si se elige no refactorizar se elige no pagar la deuda técnica que con el tiempo demostrará que la posibilidad de fracaso aumenta”.

La clave es mantener la deuda técnica bajo control y esto requiere un esfuerzo desde la programación de base como de las tareas adicionales de refactorización, de acuerdo siempre con las necesidades de quién paga, el cual debe estar siempre informado de las consecuencias que tiene realizar desarrollos sobre un software de baja calidad.

En mis artículos utilizo mucho los términos sistemas de información, producto, etc… en referencia al software que estamos desarrollando en un proyecto.

Hay quienes piensan que la terminología más adecuada debería ser solución porque es precisamente eso lo que estamos intentando hacer: resolver una problemática de un cliente (interno o externo).

Es muy importante tener en cuenta ese aspecto: el cliente realiza una inversión para tratar de mejorar la calidad y cantidad de los resultados de alguna de sus áreas de negocio, para tener una visión global de la información y extraer conocimiento de ella, etc…

A alto nivel su expectativa es mejorar y nuestro objetivo debe ser dar una solución a esa expectativa.

Esta sencilla ecuación se rompe en el momento en el que el proveedor centra su objetivo en el beneficio y no en las expectativas del cliente, pasando a ser el proyecto su solución y no de quién la está pagando. Esto es muy común y hace mucho daño al negocio y a nuestra profesión porque la calidad final del resultado se resiente y la imagen de todos (porque se nos mete a todos en el mismo saco) queda muy deteriorada.

No me invento nada, en esta época de crisis, muchas organizaciones en lugar de invertir en TIC para tratar de conseguir ventajas competitivas, huyen porque no creen en un retorno de la inversión.

Las empresas trabajan para ganar dinero, hasta ahí de acuerdo, pero esa aspiración legítima no debe justificar que el cliente sea el sacrificado.

En muchas ocasiones el cliente, ya sea, por falta de implicación, por no haber elegido el momento más adecuado para realizar el proyecto, por la aparición de otras prioridades que deben atender, etc…, es culpable de que los resultados no sean los esperados, pero en otros muchos casos sí que cumple, sí que trata de poner los medios para que el proyecto vaya adelante y sin embargo no es tratado justamente por el proveedor.

Su enunciado es el siguiente: “La calidad de los sistemas comienza a disminuir a menos que se mantengan de forma rigurosa y se adapten a los cambios en su entorno de funcionamiento (operacional)”.

En esta ley, Lehman trata el problema de la disminución de la calidad desde diferentes puntos de vista:

– El usuario tiende a ser más exigente conforme mayor sea la inversión dedicada a la evolución del producto y conforme se den cuenta (independientemente de que sepan interpretar su complejidad o no) de la maleabilidad del software.

– La calidad del software se ve afectada por en incremento de la complejidad del sistema conforme se va evolucionando y eso afecta a diferentes escalas: codificación/arquitectura (deuda técnica), usabilidad, etc…

– Por otro la propia convivencia del sistema con su entorno tecnológico (software y hardware), el cual evoluciona de la misma forma que los sistemas y en muchos casos con características muy similares. En esa evolución se tratan de corregir fallos de seguridad, se trata de dar una mayor estabilidad, a la par de incluir nuevas funcionalidades que puedan resultar de utilidad (y distinguirla de otras opciones del mercado).

Si un sistema no se adapta a esos cambios y las características de los nuevos entornos operacionales que se estén montando no son compatibles, estamos acotando el sistema a seguir subsistiendo con versiones en muchos casos sin soporte de los mismos y que además, se irá quedando marginada porque el esfuerzo central del Departamento de Sistemas se centrará en los entornos en los que se encuentre el grueso de los sistemas de información de la organización, además de aquellos que sean considerados críticos.

El alcance de esta séptima ley se puede extender al propio framework de desarrollo del producto y al conjunto de librerías dependientes que utilice, de manera que surgen nuevas versiones de las mismas que mejoran las anteriores a la vez que corrigen defectos en las mismas.

También puede ser extensible a una menor calidad como consecuencia de no aplicar medidas conforme se incrementa la complejidad del producto (en este caso se asimilaría a la segunda ley de Lehman).