Code Refactoring o refactorizando código

El término code refactoring  (o refactorizar el código) aparece de forma frecuente en el ambiente de quienes desarrollamos software.

Muchas veces hemos leído o escuchado hablar de “refactorizar”, sobre sobre sus ventajas, sobre la necesidad de hacerlo, los riesgos de hacerlo ¿o de no hacerlo?, y otras tantas cosas relacionadas con él.

¿Qué es refactoring?

Una definición ampliamente aceptada dentro de la ingeniería de software dice que la refactorización es una técnica disciplinada para mejorar el diseño del código sin introducir cambios en la funcionalidad que provee el mismo.

Es decir que cuando refactorizamos, estamos produciendo mejoras en el código, lo estamos simplificando, estamos facilitando su mantenimiento pero sin modificar su comportamiento.

¡A no confundirse!

Un aspecto importante que debemos tener en cuenta en esto de la refactorización (y que muchas veces lleva a confusión o malinterpretación) es que con la refactorización no se arreglan bugs, no se alteran ni se introducen nuevas funcionalidades; la mejora del código debe ser separada de las funcionalidades que este brinda.

Sin embargo, en ocasiones una cosa requiere de la otra…

Cualquiera que escriba software ha podido disfrutar o padecer un código heredado cuando debe interactuar con él para llevar adelante un cambio en la funcionalidad. Quién no ha encontrado una declaración del tipo

a = B * c / 2 en la línea 1854 de un programa. (1)

Vaya uno a saber en qué estaba pensando el colega programador cuando escribió la fórmula para calcular el área del triángulo. . .

area = base * altura / 2 (2)

Con (1) y (2) obtenemos el mismo resultado, pero… se ven distintos, ¿no?

¿Qué quiero significar con ello? Que muchas veces, antes de poner manos a la obra en la funcionalidad, es conveniente y hasta imprescindible tener a mano una (gracias Mario Benedetti) refactorización de código.

Si vemos el código como una caja negra, cuando refactorizamos estamos alterando su interior, sin modificar su comportamiento externo.

La apariencia externa sigue siendo la misma caja negra. Sin embargo, cuando nos introducimos en él para trabajar, hay una enorme diferencia entre el antes y el después de una refactorización.

La visión del maestro

Tratándose de temas de ingeniería de software, no podemos omitir el punto de vista de un referente en la materia, como lo es Martin Fowler.

Al definir la refactorización en su libro Refactoring – Improving the Design of Existing Code, Fowler lo hace de dos formas:

Como sustantivo: un cambio realizado en la estructura interna del software para que sea más fácil de entender y más económico de modificar, sin cambiar su comportamiento observable.

Como verbo: restructurar el software aplicando una serie de refactorizaciones sin cambiar su comportamiento observable.

Y para despejar cualquier duda, Fowler aclara que refactorizar no es limpiar código (que sabemos que muchas veces se utilizan como sinónimos). Limpiar código es una técnica para mejorar la salud de un código.

El autor emplea el término reestructuración para hacer referencia a cualquier tipo de reorganización o limpieza de código fuente, considerando a la refactorización como un tipo particular de reestructuración.

¿En qué consiste refactorizar?

La refactorización radica en aplicar pequeños pasos o transformaciones que preservan el comportamiento; al mismo tiempo que encadenando una secuencia de estas transformaciones se logra un cambio significativo manteniendo inalterable el comportamiento.

Cada refactorización individual, tiene las siguientes particularidades:

  • ser muy pequeña en sí misma,
  • de preservar el comportamiento y
  • de evitar que el código permanezca “roto” durante un lapso prolongado;

Esto permite que cuando estoy refactorizando, me pueda detener en cualquier momento, aun cuando no haya finalizado totalmente de hacerlo.

Puesto que cada refactorización es pequeña, las chances de que salga mal son menores.

El sistema se mantiene completamente operacional después de cada refactorización, por lo que las posibilidades de que un sistema deje de funcionar durante la reestructuración son sensiblemente inferiores.

A decir de Fowler:

Si alguien dice que su código se rompió durante un par de días mientras se refactorizaba, puede estar bastante seguro de que no lo estaban refactorizando.”

Otro bocado de Fowler para degustar:

Advierte que a las personas que ven la refactorización por primera vez les puede resultar ineficaz dar muchos pequeños pasos, en lugar de dar un solo paso más grande que a priori resultaría suficiente. A ello responde que con pequeños pasos uno puede avanzar más rápido, porque ellos se ajustan muy bien y fundamentalmente porque no se invierte tiempo depurando.

¿Para qué refactorizar?

Partiendo de la premisa que tenemos un software que cumple con la funcionalidad para el que fue escrito (si no cumple, refactorizando no solucionaremos el problema), es decir que funciona, algunos se preguntarán para qué tocarlo (recordar el precepto que dice que si algo funciona, ¿para qué tocarlo?)…

Sintéticamente podemos decir que, refactorizando:

  • Mejoramos el diseño del software.
  • Facilitamos el entendimiento del código.
  • Facilitamos la depuración de bugs o errores.

En resumen, la refactorización es una herramienta valiosa que ayuda a controlar y mantener el código, permitiendo desarrollar más rápidamente.

Conclusiones

El desarrollo de software supone un desafío intelectual y creativo que, como tal, no está exento de errores, interpretaciones, gustos y cualidades.

Sin embargo cuando hablamos de refactorización, estamos hablando de un mejor diseño interno, una mejor legibilidad y minimización de errores; es casi unánime la percepción de mejoramiento de calidad.

Alguien escribió a modo de broma en algún lugar:

No estoy seguro si una refactorización hizo el código más entendible, o si simplemente lo entiendo mejor porque gasté horas en refactorizarlo