Introducción
Muchas veces sucede que al crear
aplicaciones avanzamos sobre el desarrollo del código fuente
acumulando elementos con estructuras poco estables que ponen en
riesgo el funcionamiento general o parcial del programa.
Si te has preguntado cómo mejorar tus
aplicaciones es hora de que conozcas un poco más acerca de la
refactorización
¿Qué es refactoring?
Es una de las herramientas que podemos
implementar en el desarrollo de nuestras aplicaciones para
minimizar, corregir y evitar acumulaciones de estructuras
deficientes (bugs) dentro del desarrollo de nuestro código.
Es decir que en pocas palabras el refactoring es
un proceso a través del cual se busca mejorar el funcionamiento de
un código fuente sin agregar funcionalidades.
Aunque hoy en día la refactorización
de código se aprende en las lecciones básicas de ingeniería de
software, también es una pieza fundamental que complementa las
buenas prácticas de todo programador avanzado.
¿Para qué sirve el
refactoring?
Como hemos dicho, la refactorización sirve
para mejorar nuestro código transformándolo en un sistema más
estable, más compatible y también más legible para otros
programadores,
sin la necesidad de crear nuevas funcionalidades.
Al hacer refactoring de manera
iterativa podremos evitar acumular errores en cada nueva
implementación que realicemos, lo que impedirá que tengamos que
volver a escribir todo el código desde cero por más que el número de
sectores deficientes o errores dentro de las estructuras parezca
abultado.
Refactoring - ¿Cómo funciona?
La refactorización funciona como un
proceso de limpieza y ordenamiento del código fuente sobre el que
estamos trabajando. Es decir que, para lograr obtener un refactoring
exitoso es necesario trabajar de manera ordenada. Para hacerlo
podemos dividir este proceso en 6 etapas:
-
ANALIZAR E IDENTIFICAR: En
esta etapa es importante conocer
de manera precisa los problemas que presenta el código a
refactorizar. Para
ello podremos revisar la documentación del proyecto, implementar
la detección de códecs
smells e
identificar los problemas a resolver dentro del diseño según el
orden prioritario que cada bug presenta.
-
PLANTEAR LA SOLUCIÓN: En
esta etapa se plantean las diferentes soluciones a implementar
para cada conflicto identificado. Es importante tener en cuenta
que, cada
refactoring que vayamos a ejecutar debe presentar soluciones en
pasos simples, pequeños y seguros. En
este punto también es necesario documentar el estado de los
escenarios a modificar para que luego podamos agregar estas
tareas al backlog de actividades futuras a realizar.
-
PRIORIZACIÓN DE ACTIVIDADES: Durante
el desarrollo de software la mayoría de proyectos cuentan con un
tiempo de ejecución finito por lo que, conocer
y atacar en primeras instancias los procesos de refactorización
más relevantes enumerados en el backlocg será fundamental.
Esto es importante, ya que si llegado el caso no
podamos completar todas las actividades pendientes estaremos
seguros de haber refactorizado los sectores más importantes
primero. Podemos medir su relevancia según el nivel de impacto,
el nivel de esfuerzo y la relación que dicha actividad presenta
entre ambos niveles.
-
IMPLEMENTACIÓN – REFACTORIZACIÓN: Esta
es la etapa donde se
aplican los cambios en el sistema. Para
ello siempre debemos
verificar la cobertura de los test utilizados antes de
implementar las modificaciones en cada escenario.
Una vez verificado que disponemos de los test
necesarios, se refactoriza el código que deseamos mejorar. A
partir de ahí nuestros test dejarán de pasar, con lo cual se
deben adaptar al cambio hecho para que vuelvan a pasar.
Este método de desarrollo se lo conoce como rojo-verde. Dónde
rojo indica la necesidad de adaptar los test a los cambios
hechos (la refactorización) y verde que nuestros test ya están
adaptados a los cambios. Por
lo tanto, el método refactoring red → green, es un método
reiterativo. Es decir, lo podemos aplicar todas las veces que
deseemos mejorar la calidad de nuestro código.
-
MEDICIÓN: A
través de un análisis basado en la documentación, un análisis
subjetivo del grupo de trabajo y una evaluación de los
resultados podremos corroborar si la refactorización ha sido
funcional para mejorar el sistema.
-
EVALUACIÓN: Los
objetivos de esta etapa son determinar si la refactorización ha
sido exitosa o debemos realizar una nueva iteración de todo el
proceso
Tipos de errores que
se pueden corregir refactorizando
A través del refactoring podemos
corregir muchos de los errores acumulados en nuestro código
provenientes de una gran variedad de fuentes distintas.
Entre las refactorizaciones más
comunes suelen corregirse errores de código innecesario, código
duplicado, listas de parámetros muy extensas, clases con muchas
funciones o muchas responsabilidades, así como también errores
provocados por clases intermedias (middle man).
Técnicas de
refactorización
Martin Fowler y Kent Beck profundizan en cada una de
las técnicas de refactorización más conocidas en su libro Refactoring:
Improving the Design of Existing Code por
lo que si estás interesado en aprender sobre técnicas de
refactorización te recomendamos leerlo.
A continuación haremos un repaso
dividiendo las técnicas en 6 grupos diferentes:
1. Métodos de composición (Composing
Method)
2. Mover entidades entre objetos (Moving
Features between Objects):
3. Organización de Datos (Organizing
Data)
-
Change Value to Reference
-
Change Reference to Value
-
Duplicate Observed Data
-
Self Encapsulate Field
-
Replace Data Value with Object
-
Replace Array with Object
-
Replace Type Code with Subclasses
-
Replace Type Code with State/Strategy
-
Replace Subclass with Fields
-
Change Unidirectional Association
to Bidirectional
-
Change Bidirectional Association
to Unidirectional
-
Encapsulate Field
-
Encapsulate Collection
-
Replace Magic Number with Symbolic
Constant
-
Replace Type Code with Class
4 Simplificar Expresiones
Condicionales (Simplifying Conditional Expressions)
-
Consolidate Conditional Expression
-
Consolidate Duplicate Conditional
Fragments
-
Decompose Conditional
-
Replace Conditional with
Polymorphism
-
Remove Control Flag
-
Replace Nested Conditional with
Guard Clauses
-
Introduce Null Object
-
Introduce Assertion
5 Simplificación de Llamadas a Métodos (Simplifying
Method Calls)
-
Add Parameter
-
Remove Parameter
-
Rename Method
-
Separate Query from Modifier
-
Parameterize Method
-
Introduce Parameter Object
-
Preserve Whole Object
-
Remove Setting Method
-
Replace Parameter with Explicit
Methods
-
Replace Parameter with Method Call
-
Hide Method
-
Replace Constructor with Factory
Method
-
Replace Error Code with Exception
-
Replace Exception w
6 Lidiar con la Generalización (Dealing
with Generalization)
Conclusión
El uso correcto de la refactorización durante las diferentes etapas
de elaboración de un proyecto puede beneficiar en gran medida la
implementación de otras herramientas fundamentales que todo
programador debe conocer, estudiar y utilizar dentro de las
buenas prácticas de programación informática.
Desde Craft
Code te
animamos a desarrollar tus habilidades para diseñar código cada vez
más limpio, escalable, reutilizable simple de compartir y ampliar