archivo

Archivo de la etiqueta: deuda técnica

La siguiente cita de Bertrand Meyer puede crear algo de controversia (traducción libre): “Que esté correcto es claramente la primera calidad. Si un sistema no hace lo que se supone que debe hacer, entonces todo lo demás importa poco”.

¿Por qué digo que es controvertida? Si se entiende a partir de ella que el fin último es satisfacer las necesidades de los usuarios a través de un producto que se aproxime a lo que estaban esperando y que para eso todo vale, puede considerarse como polémica porque la calidad del software va más allá de eso, es más, probablemente sin esos otros ingredientes resulta mucho más complicado conseguir ese objetivo.

De hecho, si en el software se va acumulando tanta deuda técnica que hace prácticamente inmanejables las tareas de evolución del producto, tenemos un problema importante porque si bien se ha podido conseguir un producto del que estén satisfecho los usuarios, es posible que esa satisfacción sea efímera porque lo más probable es que el producto tenga que modificarse en un futuro, sea a corto, medio o largo plazo y si como consecuencia de las dificultades para adaptar el sistema al cambio no es posible en forma y/o en tiempo (y/o en la cantidad de dinero que es posible invertir), el éxito inicial se habrá convertido en un espejismo.

Como es lógico, Bertrand Meyer pone sobre la mesa algo muy importante y que los desarrolladores a veces perdemos de vista y es que, por regla general, desarrollamos un software para que lo utilice un tercero y no para:

– Seguir procesos por el simple hecho de seguirlos, sin tener en cuenta la realidad y contexto del proyecto y producto en el que estamos trabajando.

– Seguir determinadas técnicas que pudiendo ser beneficiosas no resultan prácticas para este proyecto concreto.

– Ponernos a hacer experimentos que si no tienen como fin obtener un aprendizaje que permita dar un mayor valor al producto directa o indirectamente, se deberían evitar.

Este es uno de los principales problemas del desarrollo de software y da igual la metodología o estrategia que estés aplicando.

Los equipos y desarrolladores que saben que la calidad se obtiene en el día a día de tu trabajo y no mediante controles en momentos puntuales del proyecto, funcionan mejor y obtienen, en consecuencia, mejores resultados.

El problema es que se cree que de esta forma se avanza más deprisa pero no deja de ser una ilusión porque si te echan para atrás una entrega en reiteradas ocasiones todo lo que se adelantó se termina convirtiendo en retrasos y no se trata solo de plazos, sino de esfuerzo que se tiene que volver a invertir (más costes).

Tampoco se trata de problemas de índole funcional o de detección de defectos, se trata también de la propia calidad de la arquitectura y del código, de la deuda técnica. La refactorización consigue disminuir esta problemática y es una buena práctica pero lo ideal es que venga acompañada con intención en el desarrollo, es decir, de intentar que el código y las decisiones relacionadas con la arquitectura sea lo mejor posible de serie.

Hablo de mejor posible, no de perfección, hay un camino muy largo entre ambos conceptos, teniendo en cuenta que la perfección en el desarrollo de software no es más que un concepto abstracto y retórico.

¿Cuándo queda para que el proyecto termine?.

Interesante visión la que plantea la Ley de Hartree: “El tiempo desde ahora hasta la finalización del proyecto tiende a ser constante”.

Sería más exacto si en lugar de hablar de proyecto hablásemos de ciclo de vida del producto software, ya que se entiende al proyecto como un conjunto de actividades que se realizan en el tiempo para conseguir unos resultados (mucho más cortoplacista y concreta de lo que sería el ciclo de vida).

Si bien, nos encontramos pese a todo, con proyectos que prácticamente no parecen tener fin, ya sea porque los objetivos (para los cuales se realizan esas actividades) son demasiado abiertos o ambiguos y/o porque la ejecución de las trabajos por parte del equipo de desarrollo es deficiente, teniéndose que volver a realizar de nuevo o parcialmente determinadas funcionalidades, por una deuda técnica elevada, lo que hace que la mantenibilidad o evolución del sistema requiera más tiempo y esfuerzo, etc…

Ya sea tomando como referencia los proyectos o el ciclo de vida, lo que sí resulta interesante de esta ley son los mensajes que podemos interpretar a partir de ella:

– Los proyectos de desarrollo de software suelen tener objetivos demasiado abiertos o ambiguos.
– Las estimaciones son menos precisas cuanto más cerca nos encontremos del inicio del proyecto.
– La deuda técnica de manera paulatina hace más complejo el proceso de desarrollo de software.
– Un producto software de manera inherente tiende a ser evolucionado (ver leyes de Lehman).

También resulta fundamental que los desarrolladores entiendan que la detección de defectos es un trabajo que empieza desde antes de escribir la primera línea de código. Si estamos tratando de describir con más detalle una historia de usuario y no contrastamos de manera adecuada con los responsables funcionales si hemos entendido bien lo que quieren y esperan, estaremos introduciendo de partida defectos que tendrán su reflejo en el código.

Por tanto, la detección de defectos debe empezar desde etapas muy tempranas y de manera ininterrumpida debe continuar durante todo el proceso de desarrollo y es un proceso en el que interviene el equipo de desarrollo, los propios usuarios, otros departamentos (como por ejemplo sistemas) y en el que pueden participar especialistas integrados o no en el equipo de desarrollo (si no forman parte directamente del equipo, al menos sí que deberían tener un cierto contacto para que puedan entender determinadas decisiones que se toman en el proyecto, entiendan el fundamento del producto que se está haciendo y puedan conocer las expectativas del usuario).

Los defectos pueden abarcar áreas funcionales y no funcionales por lo que el ámbito de actuación para detectarlos es bastante amplio. Pese a eso, no debemos olvidarnos de otro factor muy importante en la calidad del software como es la deuda técnica para servirnos de indicador sobre el grado de mantenibilidad (y su coste asociado) que tiene el producto software.

Cada persona tiene su propia percepción de la realidad. La comprensión de lo que se ve está modulada por una infinidad de variables que hace que incluso que una misma persona sobre un mismo hecho pueda tener percepciones distintas, aún existiendo un intervalo de tiempo pequeño entre ellas.

Ante esta situación, ¿qué podemos decir de las diferentes visiones que existen sobre la calidad del software? Pues lo mismo, existe una para cada persona, si bien, en muchos casos las diferencias son simples matices que hacen que entendamos que nuestra visión de la misma es igual que la de otros.

Es decir, a lo más que se podrá llegar es a agrupar a personas que tienen pensamientos similares sobre lo que debe ser, los cuales muy probablemente iran cambiando de grupo en función de su evolución profesional, conocimientos y experiencias.

Parece que es algo común asociar calidad con el software que funciona pero, ¿qué es el software que funciona?, ¿dónde está el umbral para determinar que un software funciona? No es adecuado establecer de antemano cuáles son esos límites porque no serán los mismos en una aplicación crítica que en otra que no lo es.

También parece que es común asociar calidad con software mantenible pero, volvemos a los mismo, ¿qué entendemos por software mantenible?, ¿software que sea fácilmente evolucionable?, ¿software con una deuda técnica acorde a sus características e inversión realizada?, ¿todo eso y más variables?.

En el fragor de la batalla, cuando los proyectos empiezan a tener problemas se prioriza que el “software funcione” sobre el “software mantenible” porque se entiende que lo segundo no sirve de nada si no se consigue lo primero.

Este error es muy común porque en el caso de que “no funcione” mejor que tengamos un software donde se pueda realizar con facilidad evoluciones y correcciones.

No se trata de priorizar la mantenibilidad porque si lo hacemos sin pensar en “que funcione” perderemos intención y se tirará, más adelante, mucho código que ha costado mucho esfuerzo poner en pie.

Para otro no se puede entender la calidad sin el cumplimiento de los plazos, sin la relación coste/beneficio, sin atender a los procesos de calidad y desarrollo de software de la organización, sin la existencia de documentación, etc…

Es difícil convencer a alguien de que cambie su visión sobre la calidad del software porque generalmente esos cambios de opinión vendrán dados por la propia experiencia personal, teniendo en cuenta que para poder cambiar y evolucionar hay que querer.

Es positivo intercambiar apreciones sobre este tema porque incluso en posiciones divergentes es posible encontrar nuevas variables a tener en cuenta o considerar diferentes puntos de vista sobre otras en las que ya creemos.

Para Bertrand Meyer: “El único gran enemigo de fiabilidad (y tal vez la calidad del software en general) es la complejidad”.

En mi opinión hay muchas más variables pero sí que es cierto que la complejidad condiciona, sin lugar a dudas, el resultado final de un producto, su usabilidad y la capacidad de realizar mantenimientos sobre él o, lo que es lo mismo, la capacidad de evolucionarlo.

Si nos dejamos seguir por las modas, si se imponen restricciones técnicas o de arquitectura que no condicionan sobre manera el proyecto, si miramos la solución como un juguete o un banco de pruebas, probablemente se le esté añadiendo la resultado final una complejidad innecesaria y que después va a resultar muy costosa de eliminar.

Si el producto se empieza a “engordar” con funcionalidades que no son necesarias, con módulos que no tienen nada que ver con su objeto final (porque resulta más barato incluirlos en la plataforma que crear un sistema desde cero para ellas), etc…, también se estará añadiendo complejidad que hay podido ser evitable.

A más complejidad más probabilidad de que existan errores y que no sean detectados. A más complejidad más deuda técnica.

La inclusión de pruebas unitarias, la automatización del testing, la inclusión de software para trazar comportamientos irregulares de una aplicación en un servidor de aplicaciones o de base de datos, etc…, son en algunos casos buenas prácticas y en otros buenas soluciones, siempre que se apliquen adecuadamente, y que pueden ayudar no solo a prevenir problemas sino a detectar la causa de otros que ya se han materializado.

Pero no solo eso, el cambio de versión de un determinado backend con el objetivo, por ejemplo, de mejorar el rendimiento de la aplicación ante una previsión de una mayor carga del sistema puede ser origen de nuevas anomalías, por más que pensemos que resulta improbable que se produzcan esos efectos.

Es importante que tengamos en cuenta que son elementos que se añaden ya sea al código o a la infraestructura y que pueden provocar a la vez nuevos problemas, en la misma aplicación o en otras. Esos problemas pueden ser el resultado de la incompatibilidad con otros artefactos o por errores humanos a la hora de desarrollarlos, configurarlos o instalarlos.

Es cierto que un sistema robusto, con una deuda técnica bajo control y la existencia dentro del departamento de TIC de mecanismos que permitan gestionar adecuadamente el cambio (en la inclusión o sustitución de elementos de infraestructura físicos y lógicos) reducirán la probabilidad de que estos problemas se produzcan, y mayor será la reducción cuanto más se invierta en ello (si la inversión se realiza de manera efectiva), hay que medir siempre la criticidad de los sistemas que estamos manejando y las consecuencias de su falta de disponibilidad o de tener un comportamiento anómalo.

Esta situación es la base de la paradoja del pesticida de Bruce Beizer: “Cada método que utilices para prevenir o encontrar errores deja un residuo de errores sutiles contra los que esos métodos resultan ineficaces”.

Esto nos lleva a la necesidad de ser prudentes, a la necesidad de medir el riesgo a la hora de realizar determinadas actuaciones, a la necesidad de no dar nada por sentado y a ampliar nuestro rango de visión cuando empecemos a detectar anomalías en un sistema y nos resulte complicado detectar su origen.