El Refactoring es una práctica fundamental en el desarrollo del software, que sin embargo, se deja de lado demasiado a menudo debido a las presiones para cumplir con las fechas de entrega.
No es algo “opcional” que se puede dejar “para cuando haya tiempo”. Al contrario. Es igual a la limpieza del taller mecánico, debe realizarse constantemente, sino se empezarán a perder piezas, herramientas, y la productividad se verá afectada gravemente. Nuestro proyecto comenzará a caer víctima de la ley de la entropía.
¿Y qué es el refactoring? Muy fácil. Consiste en realizar mejoras al código sin modificar su funcionalidad externa. Es decir, sin que el usuario de nuestro código tenga que enterarse de que hubo un cambio. No consiste en introducir nuevas funciones ni arreglar errores, sólo estamos optimizando lo que ya existe.
Quizás sea mejor ilustrar con un ejemplo muy simplificado, uno de mis refactorings favoritos, proveniente del catálogo de Martin Fowler.
Reemplazar Condicionales Anidados con Guards
Es bastante frecuente encontrar código como este:
public bool AvanzarSemaforo() { if(_semaforo.Estado == EstadoSemaforo.OK) { if(_semaforo.Color != ColorSemaforo.Rojo) { if(_semaforo.Color != ColorSemaforo.Amarillo) { return true; } } } return false; }
El problema con este antipatrón que ha sido llamado “punta de flecha” [1] por la forma que toma el código, es que aumenta innecesariamente la complejidad del código, dificultando su comprensión a la hora del mantenimiento.
La solución consiste en invertir las comparaciones booleanas, colocando los casos excepcionales al principio del método en forma de guardas y a continuación el camino normal de la ejecución:
public bool AvanzarSemaforo() { if(_semaforo.Estado != EstadoSemaforo.OK || _semaforo.Color == ColorSemaforo.Rojo || _semaforo.Color == ColorSemaforo.Amarillo) { return false } return true; }
Como podemos ver, el método es ahora mucho más breve y comprensible.
Programas como Resharper automatizan este tipo de refactorings e incluso los sugieren automáticamente. Sin embargo no es difícil hacerlo de forma manual, siempre teniendo cuidado de no alterar la funcionalidad original, que es el objetivo fundamental de todo refactoring.
[1] Sean Chambers, Simone Chiaretta: 31 Days of Refactoring. pág 38. Enlace: http://lostechies.com/e-books