archivo

Archivo de la etiqueta: lava seca

Que el software se deteriora conforme se va evolucionando es un hecho a partir del momento en que el sistema tiene implementadas el conjunto de funcionalidades que el usuario realmente necesita (el problema de esto es que casi siempre resulta complicado saber cuándo se llega a este punto y que incluso llegando a él habrá funcionalidades adicionales a las estrictamente necesarias que también se habrán implementado).

Este deterioro es aplicable a nivel funcional (se implementarán nuevas funcionalidades muchas de las cuales serán innecesarias, lo que hará más complejo el uso del sistema, introducirá nuevos errores y provocará probablemente efectos colaterales) y técnico (antipatrones ancla de barco y lava seca, incremento de la complejidad, etc…).

Hablo en términos generales, ya que incluso en estos casos es posible mejorar el sistema en ambos aspectos.

Ahora bien, me parece muy interesante poneros la siguiente reflexión de Dave Thomas, ya que la deuda técnica es una resistencia que tiene el software pero de cara a su evolución y en ese sentido es importante tenerla en cuenta, no obstante la deuda técnica no actúa si el software está en reposo (eso de que no actúa también es relativo ya que un sistema con una deuda técnica alta es serio candidato a dar muchos problemas) si vemos dicho concepto desde el punto de vista de la mantenibilidad: “La métrica del coste del cambio empieza a correr cuando tomas una decisión. Si no tomas una decisión, entonces no hay nada que cambiar y la curva contínúa plana”.

Por tanto, la degradación no debería considerarse función del tiempo sino de la evolución. Sin embargo se asocia generalmente con el tiempo y tiene una cierta lógica ya que la evolución es consecuencia de actuaciones que se realizan en el sistema conforme avanza el tiempo.

La reducción de la deuda técnica y la mejora en la legibilidad del código, así como evitar la consolidación de antipatrones del tipo ancla de barco o lava seca son algunos de los objetivos principales de la refactorización.

Hay quienes incluyen la refactorización como una fase final del desarrollo de una determinada tarea y otros que la incluyen como tareas concretas. Habría que analizar qué es más conveniente en cada caso, lo que en cualquier caso resulta incontestable son los beneficios de la refactorización. Pese a ello, muchos equipos de desarrollo no la tienen en cuenta entre sus hábitos de desarrollo y muchos clientes no valoran la realización de este tipo de actividades (tal vez porque no se les ha explicado bien sus ventajas).

La siguiente cita de Ron Jeffries contextualiza perfectamente la refactorización: “La razón por la cocina es un desastre no es porque la cocina esté mal diseñada sino porque no se lavan los platos después de cada comida”.

Los desarrolladores somos auténticos expertos en meternos en charcos. Muchas veces nos empujan a ellos, en otras somos nosotros los que nos metemos hasta el fondo.

De eso trata este antipatrón, de nuestra tendencia a complicar proyectos sin necesidad, veamos algunos ejemplos:

– Con el objeto de superar las expectativas del usuario o sorprenderle, se deciden afrontar funcionalidades con prioridad muy baja que se consideran poco complejas, aprovechando los remanentes de tiempo en el desarrollo normal del proyecto.

En muchos casos, lo que parecía simple no lo es tanto y se terminan desechando (muchas veces de manera poco limpia, antipatrón “lava seca“), lo que ha supuesto un esfuerzo que no ha servido para nada, además de una pérdida de enfoque en los objetivos principales del proyecto

– Se aplican soluciones experimentales (prueba de una nueva tecnología, un nuevo framework, unos nuevos componentes) en lugar de aplicar soluciones conocidas.

– Sin entrar en un análisis riguroso del sistema o de determinadas funcionalidades, nos aventuramos a dar unos plazos muy exigentes (sin que nadie no los haya impuesto).

Nos encontramos con este antipatrón cuando ante un sistema de información de complejidad y tamaño medio/alto, con una deuda técnica alta, se solicita la realización de tareas de mantenimiento, generalmente evolutivo, de cierta envergadura, las cuáles deberían ejecutarse en un plazo de tiempo muy ajustado y se centran los esfuerzos en intentar conseguir ese objetivo, independientemente de que el producto vea incrementada su deuda técnica y complejidad.

El primer problema que nos encontramos es la existencia de una restricción temporal que condiciona los trabajos, lo que hace que se enfoquen los esfuerzos en “apagar el incendio”, dejando de lado la aplicación de determinadas buenas prácticas y controles de calidad del software si estos pudieran frenar el avance de la ejecución de las tareas.

Esto hace que el plan de proyecto se centre en dar una respuesta a la situación, dejando para el final la realización de tareas que mitiguen la deuda técnica y la simplificación de funcionalidades eliminando funcionalidades o código que no ya no tienen utilidad (ver antipatrones lava seca y ancla de barco). ¿Qué es lo que suele pasar? Pues que al final no haya tiempo para realizar esos ajustes, ya sea porque nos hemos quedado sin presupuesto y/o aparecen nuevos fuegos que ir mitigando.

Esa restricción temporal puede estar justificada ante la necesidad de adaptar un sistema de información a una normativa o para adaptar el sistema a un cambio en procesos o a un nuevo proceso que resultan esenciales para el funcionamiento de la organización y que de no estar en los plazos fijados podría suponer un importante perjuicio económico que podría incluso afectar seriamente no solo a los balances, sino incluso a la propia viabilidad de la compañía.

Otras veces la restricción temporal, pese a que pueda estar sustentada por ciertos criterios objetivos, no deja de ser un capricho de cierto personal directivo a los que un día en un “alarde de creatividad” deciden que es necesario realizar ajustes en un sistema o incluirle nuevos módulos.

El siguiente problema es la realización de cambios de cierta magnitud en un sistema con una deuda técnica elevada, que implican que cualquier tarea de desarrollo sobre el mismo (sobre todo aquellas que supongan modificaciones en módulos ya implementados) cueste muchísimo más esfuerzo (como correr con un vendaval de viento en contra, con carga en una mochila y con pegamento en la suela de las zapatillas), además de incrementarse la probabilidad de errores, tanto por posibles efectos colaterales como por la presión de ejecutar trabajo rápidamente, dejando de lado la realización de determinadas prácticas de aseguramiento de la calidad del software.

Al final, en el caso de que cumplamos el hito temporal (algo que en aquellos casos donde los plazos sean muy ajustados solo será posible priorizando tareas, teniendo a todos los stakeholders muy implicados y acertando mucho), tendremos un producto más complejo, más costoso de mantener (si cabe) y bastante más inestable.

El antipatrón software inflado hace referencia a múltiples circunstancias que se pueden producir en un proyecto de desarrollo de software, aquí os indico algunas de ellas:

– Desarrollar un software sin tener en cuenta una utilización adecuada de los recursos.

Es cierto que el precio de los recursos hardware y los avances tecnológicos dan mucho margen de maniobra, sin embargo esto no quita que el mantenimiento de un CPD sea caro, que en entornos de producción coexisten multitud de aplicaciones que comparten recursos y que un uso inadecuado de los mismos por parte de una puede provocar problemas de disponibilidad y/o rendimiento en las otras.

Por tanto, es un antipatrón desarrollar sin tener en cuenta que es necesario optimizar la utilización de recursos externos al sistema (incluyendo, también, ¿por qué no? recursos software).

Pero no todo es software y hardware. También están las personas y un software desarrollado con alta deuda técnica también se debe considerar un software inflado porque el coste de mantenimiento del mismo será muy importante en relación al costo del mismo. Además, hay que tener en cuenta que muy probablemente el software que presente este tipo de características, hará un uso no adecuado de los recursos hardware y software.

– Desarrollar un software con más funcionalidades de las precisas o con complejidad adicional que no resultaba necesaria. (Otros antipatrones asociados: Ancla de barco, lava seca, complejidad no indispensable y funcionalitis acechante).

Abandonar el objetivo de simplicidad en el desarrollo del producto software lleva a esto, a matar moscas a cañonazos o a desarrollar funcionalidades o módulos que no se van a utilizar o que van a tener un uso residual. Es cierto, que muchas veces, a priori, determinadas funcionalidades parecen ser necesarias y que es tras el uso del sistema por parte del usuario cuando se descartan, sin embargo, en lugar de eliminarlas del producto software aprovechando alguna de las evoluciones del sistema, se dejan en el sistema de información.

Como no podía ser de otra forma, se considera como antipatrón, toda complejidad funcional, en arquitectura o en código que no aporta, en proporción, una solución mejor que una solución más simple.

A este antipatrón se puede llegar también a través de otros antipatrones como el de la lava seca o el ancla de barco.

Ya resulta tremendamente complicado llevar a cabo de manera efectiva un proyecto de desarrollo de software como para andar introduciendo complejidad de manera gratuita.

Coger una pala y echar al sistema más deuda técnica, añadir funcionalidad que no se va a utilizar, es hacer más grande el problema y lo mismo se llega a un punto donde resulta complicado seguir desarrollando y/o manteniendo el sistema con los medios disponibles.

Por ese motivo hay que analizar bien qué decisiones se toman (viabilidad, complejidad, utilidad, prioridad, riesgos, etc…) y siempre que sea posible realizar acciones que permitan simplificar la solución.

Presenta el mismo objetivo que el antipatrón ancla de barco, simplificar el sistema de manera que a nivel funcional, a nivel de código o a nivel documental, nos quedemos exclusivamente en cada momento con lo que representa al sistema.

Este antipatrón está orientado básicamente a esos trozos de software que dejan de tener utilidad y que no terminamos de eliminar (métodos o clases que no se utilizan, dependencias con librerías que ya no se usan, trozos de código comentados, objetos de bases de datos que ya no sirven, etc…).

Las ventajas las tendremos en una reducción de la deuda técnica, código más limpio e inteligible, reducción de efectos colaterales, etc…