archivo

Archivo de la etiqueta: refactorizar

Interesante la reflexión que Martin Fowler realiza en su libro “Refactoring: Improving the Design of Existing Code” (traducción libre): “Al compilador no le preocupa que el código sea feo o limpio. Pero cuando cambiamos el sistema, hay una persona involucrada y ahí sí que importa. Un sistema mal diseñado es complicado de modificar”.

En última instancia somos las personas las que tenemos responsabilidad sobre la deuda técnica no hay nadie más entre nosotros y el código. Es cierto que podemos apoyarnos en generadores de código y en frameworks pero es decisión de la organización, del departamento o nuestra elegirlos y en muchos casos de su evolución. Son importantes en cuanto a que te evitan la realización de tareas mecánicas y en cuanto a que marcan un camino común en el desarrollo pero hay que tener en cuenta que es importante que el código generado sea de calidad porque es posible que en un futuro el equipo que se vaya a encargar de seguir evolucionando el producto no disponga de ese generador (desgraciadamente es algo que casi nunca se tiene en cuenta).

Hay software como Sonar que utilizado de manera conjunto con un software de integración continua nos permite conocer al día el estado de la deuda técnica pero se trata solo de métricas que nos pueden alertar de situaciones anómalas (o potencialmente anómalas) al final habrá una persona (no necesariamente un gestor ya que el programador también tiene mucho que ver en esto) que tomará la decisión de refactorizar o no determinadas partes de la aplicación.

Lo más recomendable es que la propia refactorización sea parte del proceso de desarrollo que surja como algo natural y que nos apoyemos en software para conocer si hay módulos en donde el trabajo de refactorizar no ha sido suficiente o no ha sido bueno.

Hay un aspecto importante a tener en cuenta, un software que no tiene prevista una evolución ya sea porque el proceso o procesos que informatiza ya están consolidados en la herramienta o porque no merece la pena ya que la tecnología está obsoleta (y resulta más adecuado, por tanto, hacer un nuevo desarrollo) no debería ser tenido en cuenta a la hora de plantear un programa progresivo de reducción de la deuda técnica en una aplicación.

Que no se tenga prevista una evolución no quiere decir que no vaya a surgir nunca esa necesidad, ya que basta con que lo pienses como para que mañana mismo te vengan con una petición de cambio. Ahora bien, se trata de sacar el mayor provecho posible a los medios que tengamos y para ello es necesario priorizar dónde realizar este tipo de actuaciones.

Lo normal es que si tienes previsto un plan de evolución de un producto y el mismo presenta una deuda técnica inadecuada se intente dedicar parte del esfuerzo a mejorar la misma de manera que vaya mejorando la mantenibilidad del sistema. Lo mismo no hay posibilidad de hacer un cambio en profundidad del sistema ya sea porque el esfuerzo que se puede invertir esté bastante limitado y/o porque existen fuertes restricciones temporales pero siembre cualquier mejora que se pueda aplicar se agradecerá después.

Las prioridades mandan y tendrás superiores que las marquen. A veces estarás de acuerdo y otras no. Otras veces serás tú el que elijas donde invertir el esfuerzo por lo que no siempre el motivo lo podemos achacar a un tercero.

No hace falta poner ejemplos porque también conocéis el negocio y a las personas y en consecuencia sabe que determinadas tareas salvo que se tengan absolutamente interiorizadas su importancia o se hacen en su momento o lo mismo se dejan sin hacer.

Hay una cita que representa perfectamente esta situación: “Después es igual a nunca” y a la que no le falta razón en muchos casos y es prácticamente un hecho cuando estamos hablando de refactorizar el software para hacerlo más mantenible.

Quienes crean en esto y quienes en sus métodos de trabajo tengan asimilado los beneficios que supone un código y una arquitectura de calidad tratarán por todos los medios de desarrollar el mejor software posible a la primera y tendrán contemplado la realización de un esfuerzo para mejorar el código. Para aquellos que simplemente lo vean desde un aspecto teórico o no estén convencidos de la necesidad de invertir tiempo en esto siempre habrá una excusa (si viene de fuera mejor) para no hacer este trabajo.

Es importante programar al mayor nivel posible que nuestro conocimiento y experiencia nos permita. Esa debe ser la base a partir de ahí solo queda seguir aprendiendo y seguir adquiriendo experiencia para a partir de ese punto desarrollar software de mejor factura técnica.

Ahora bien, ni el conocimiento ni la experiencia son las que pulsan las teclas, somos nosotros y si no sumamos actitud a nuestra aptitud, el software que se desarrolla estará por debajo de nuestras posibilidades y por tanto estamos añadiendo deuda técnica extra que podía ser perfectamente evitable.

Es cierto que a veces no es tanto cuestión de aptitud sino el contexto en que el que trabajas donde lo mismo la presión y las prisas provocan que se priorice la ejecución de las tareas a cómo realmente se están ejecutando. Estas circunstancias condicionan el trabajo y provocan una bajada en nuestro listón potencial de calidad, pese a eso hay que intentar ajustar el software a ese nuevo listón y considerar todo lo que esté por debajo de él deuda técnica extra que añadimos al producto.

Después si la metodología de desarrollo, nuestra visión sobre lo que debe ser el producto software y las prioridades del proyecto lo permite habrá un tiempo para refactorizar pero como siempre digo esa actividad se debe realizar siempre sobre un software sobre el que se haya puesto el mayor empeño posible en hacerlo bien.

Al final toda la deuda técnica añadida al software son intereses sobre el desarrollo (y el mantenimiento) que tenemos que pagar, por lo que si hoy sale barato (desarrollar software sin tener en cuenta su mantenibilidad) que por cierto está por ver si realmente sale barato, mañana será caro, muy caro.

Me gusta mucho la siguiente cita de Bob Martin al respecto (traducción libre): “Hacer código de calidad no lleva tiempo. No hacer código de calidad sí que lleva tiempo”.

La visión de la refactorización no debe ser la de: “trato de cerrar cuanto antes las tareas que tengo asignadas que ya tendré oportunidad después de dedicar tiempo a poner el código un poco mejor”, principalmente por dos razones:

1) La mayoría de las veces, salvo que esté muy interiorizado por el equipo de trabajo y por el programador la necesidad de refactorizar y los beneficios que trae consigo, no se termina dedicando tiempo a realizar estas tareas porque continuamente van a surgir otras que se considerarán más prioritarias y sobre las que recaerá la atención. En este contexto tomar ese tipo de actitudes no es más que querer engañarnos a nosotros mismos: “finalmente no pude poner el código mejor o reducir el acoplamiento entre esas clases porque estoy hasta arriba de trabajo y no tengo tiempo”.

2) Se descuida la programación dejando para más adelante detalles que perfectamente podrían ser resueltos conforme se está trabajando. Todo es susceptible de mejorar de ahí lo útil que resulta refactorizar pero es importante que los esfuerzos dedicados a esa tarea sean los necesarios (y no más).

Es cierto que a veces las restricciones temporales imponen unas condicionen que ni permiten refactorizar y ni siquiera permite cuidar lo que se quisiera la codificación y la arquitectura. En estos casos el contexto del proyecto manda y probablemente para conseguir el resultado final en el tiempo y presupuesto establecidos habrá que sacrificar parte de su mantenibilidad y robustez.

¿Qué se puede hacer en estos casos? Lo que se pueda (realmente la situación de partida del proyecto es la culpable de todo lo demás) pero siempre con la intención de hacerlo de la mejor forma posible.

Ward Cunningham fue quien hace veinte años introdujo el concepto de deuda técnica, término que ha alcanzado una gran relevancia hasta convertirse en una variable a tener en cuenta a la hora de calificar la calidad de un determinado software.

Este autor realizó la siguiente reflexión (traducción libre): “Cuando liberamos código por primera vez lleva implícito una deuda, Un poco de deuda puede acelerar el desarrollo siempre y cuando se devuelva inmediatamente en una nueva versión… Liberar software para obtener conocimiento o feedback es una buena idea, siembre y cuando, devuelvas el préstamo que has tenido que pedir para alcanzarlo mediante la refactorización del software”.

La reflexión de Cunningham nos ofrece las siguientes conclusiones:

– En cada entrega que hagas del software siempre va a tener consigo deuda técnica adicional (el desarrollo de software tiene implícito deuda técnica la cual va creciendo conforme la aplicación se hace más grande y compleja). Que sea inherente no quiere decir que haya vía libre para que no se trate de controlar este factor de manera que se mantenga dentro de unos niveles acordes a las características del sistema y del contexto en el que se ha realizado el desarrollo.

– Si sacrificas deuda técnica a cambio de una liberación más rápida de una versión del software (ya sea por la existencia de restricciones temporales o por la necesidad de obtener feedback del usuario) necesitas reducirla cuanto antes, de lo contrario en cada actuación o iteración en el producto tendrás que cargar con la misma teniendo en cuanta, además, que seguirá creciendo.

– La reducción de deuda técnica implica refactorizar.

Tal vez de base la pregunta esté mal planteada porque estamos tratando con dos conceptos que deberían ser complementarios y obligatorios en todo desarrollo de software: que el software permita trabajar al usuario con normalidad y que sea fácilmente mantenible.

Esto es la teoría y lo que en la práctica debería de llevarse a cabo. Sin embargo, siendo realistas gran parte de los proyectos en los que trabajamos están mal planteados (plazos y presupuestos insuficientes) y hay cambios de enfoque o prioridades que ponen más complicada todavía la situación de partida, ¿qué hacemos aquí?, dirigir los esfuerzos hacia un software que funcione aplicando buenas prácticas de programación para que el código de partida tenga la mayor calidad posible.

Lo ideal es que no se tenga que llegar a la situación de tener que prescindir de la refactorización pero no sería realista no contemplar ese escenario porque todos sabemos que existe y nos lo encontramos más veces de lo que desearíamos.

Como he comentado en reiteradas ocasiones, gran parte de la suerte del proyecto se juega al inicio, cuando se negocian las condiciones y como consecuencia de las mismas se establecen las primeras restricciones al proyecto (después vendrán más).

Esto no sería tan determinante si el cliente entendiera que el desarrollo de software es de naturaleza evolutiva en un entorno de incertidumbre lo que hace que la estimación económica y temporal inicial puedan quedar echas trizas a lo largo de la ejecución del proyecto. Incluso entendiéndolo, también tendrá en muchas ocasiones restricciones presupuestarias y de otra índole, de personas que están en otro nivel de la organización y que van a estar más lejos todavía de esa realidad (y estas a su vez pueden depender de otras que estén todavía más lejos y así sucesivamente).

También los proveedores tienen mucho que ver en esas condiciones cuando presentan o aceptan ofertas fuera de mercado.