Este comienza a convertirse en uno de mis mantras favoritos: "refactorizar o morir".

Recientemente he vuelto a poner en práctica una de las mejores virtudes de realizar este tipo de trabajo continuamente. El resultado finalmente es muy satisfactorio después de muchos momentos tipo "esto está quedando fatal", "así sólo voy a llegar a una solución muy enmarañada", etc. El desánimo cunde rápido, sobre todo si se trata de un pequeño proyecto que haces a ratos por las noches o fines de semana.

No obstante, una mínima tenacidad (y seguramente tirarlo todo a la basura y volver a empezar en algún momento), te hace llegar a una buena solución que no sólo funciona, sino que además es ampliable y evolucionable con cierta facilidad.

Se habla mucho de productividad; para mí es muy sencillo describir qué es productivo y qué no en software: las soluciones fáciles son más productivas que las inextricables que sólo pueden entender sus autores, aquello que nos permite ganar velocidad de desarrollo es más productivo y con ello conseguiremos más con menos esfuerzo. Nada más. Así de contundente y simple.

Hay quienes se procupan de mejorar el código de una aplicación en alguno de sus aspectos en algún momento del trabajo: al final, cuando ya todo funciona, de vez en cuando... Sin embargo, las ventajas de incorporar estas tareas de mejora en todo momento no siempre se aprecian como productivas, mucho menos cuando nos acercamos peligrosamente a las fechas de entrega y comenzamos a dejar cabos sueltos (de los que nos acordaremos sin duda semanas o meses más tarde).

¿Por qué refactorizar cuando lo importante de una aplicación es que le funcione al cliente? Buena pregunta, y al mismo tiempo, ingenua. Quienes aún no ven claro las virtudes de invertir tiempo en este trabajo, deben saber que lo primero que se gana es velocidad de desarrollo, por tanto, productividad.

La velocidad con la que desarrollamos cualquier pieza de software viene a ser una medida de la productividad, sobre todo cuando ésta nos acerca al objetivo de entregar las funcionalidades que nos piden.

Tenemos que perseguir que el diseño o la estructura de la solución que vamos construyendo, con el tiempo nos permita avanzar más rápido y no lo contrario.

En esa aplicación en la que llevo trabajando un tiempo he ido aplicando continuamente todas las técnicas de mejora posibles: simplificaciones, abstracciones en clases de utilidad, mejora en la estructura de la solución, modularizaciones, etc, de modo que cada dos semanas he podido ver cómo el código de un commit de hace quince días no tenía nada que ver con el del último. Esto cobra especial relevancia cuando desde el principio no tenemos claro cómo vamos a implementar ciertos aspectos de la aplicación un poco complicados.

A medida que avanzamos en la solución y gracias a que aplicamos todo ese trabajo de mejora, vemos cómo poco a poco va surgiendo (emergiendo) un diseño cada vez mejor. "Mejor" es una palabra muy subjetiva y difícil de consensuar entre dos o más personas. Para mí, en software, algo es mejor si te permite desarrollar más rápido (invertir menos tiempo en la misma solución) sin perder calidad en todos los aspectos de esta.

Ese diseño elegante, sencillo, correcto, es el que nos permite a partir de un punto ganar velocidad. Llega un momento en que esto es así y es entonces cuando te das cuenta de que todo ese trabajo de mejora ha sido en realidad una buena inversión de tiempo que ahora se va a amortizar. Es como si tuviéramos una madeja de hijo que al principio cuesta mucho desenredar hasta que llega el momento en que es fácil y rápido sacar más y más hilo de ella.

En ese proyecto en concreto que estoy realizando, ha llegado un momento que he conseguido resolver todas esas partes más difíciles de manera tan sencilla y elegante que ahora lo que me queda es decorar el resto hasta finalizar la aplicación. Esto no habría sido posible si no me hubiera parado al principio con esa idea de mejorar la aplicación en todos sus aspectos.

Los comienzos de una aplicación en la que hay muchas dudas que resolver son duros, cuesta apreciar verdaderamente avances y tenemos la tentación de tirar por lo rápido y fácil, sin darnos cuenta que ese camino se volverá en nuestra contra con el tiempo.

Llega un momento en que esa mejor arquitectura y diseño para nuestro propósito es tan maduro que ya sólo nos queda seguir esa coherencia para terminar la aplicación con éxito.

Lo mejor, además, es que llegaremos al final con una solución limpia y fácil de mantener y evolucionar.

Algunas de las técnicas que he empleado hasta el momento son las siguientes:

  • A medida que el código crecía, he ido adaptando la estructura y distribución de este mucho mejor.
  • Clases largas las he ido abstrayendo en clases más concretas y sencillas con una relación lógica entre ellas (principio SRP).
  • Duplicidades las he aislado correctamente en sus servicios correspondientes (el frontend está basado en AngularJS).
  • He ido buscando continuamente todo aquello inyectable, es decir, todas aquellas dependencias que se podían sacar para implementar Inyección de Dependencias.
  • He simplificado muchos bloques de código similares con sus correspondientes funciones de utilidad.
  • Métodos de más de tres o cuatro parámetros los he ido simplificando.
  • y un largo etcétera.

Al final, todo este tipo de trabajo constituye un entrenamiento por el que terminas haciéndolo de la manera más natural y ni te planteas conscientemente el realizar esas actividades como algo separado del trabajo de desarrollo, sino como algo consustancial al mismo.

Comparte esta entrada...

¿Por qué leer El Libro Negro del Programador?

Adquirir desde:
Amazon (kindle eBook / papel)
CreateSpace (papel)
PayHip (epub / mobi / pdf)

El libro negro del programador.com
Segunda Edición - 2017

Archivo

Trabajo en...