Refactorización
La refactorización es un término técnico que se conoce popularmente como limpiar el código, es decir, pulir el código de un software para perfeccionarlo, quitar redundancias y defectos y hacerlo más eficiente. En general, esta limpieza no se centra tanto en corregir bugs o errores de código, sino en corregir deficiencias en su diseño que pueden influir en su rendimiento y escalabilidad.
Este proceso es de suma importancia para que el código sea fácil de interpretar y, por tanto, de modificar. En muchos proyectos de software, el código lo escriben entre varios desarrolladores, cada uno con su lógica, destreza y hábitos adquiridos. Si se han establecido una serie de buenas prácticas y todos los desarrolladores tienen el nivel suficiente en programación, no hará falta refactorizar tanto código.
Sin embargo, no es raro que en muchos proyectos primen las prisas y un liderazgo un tanto anárquico en lo que a la calidad del código se refiere, por lo que revisar el código y refactorizar se convertirá en una tarea periódica y esencial para garantizar que el software desarrollado sea funcional.
¿Qué fallos de código puede solucionar la refactorización?
Al refactorizar un código intentamos hacerlo más eficiente para que tenga un diseño más limpio y sea más legible tanto para los programadores como para el sistema. Así pues, hay una amplia lista de malas prácticas que ralentizan el código y que tienden a producir errores tarde o temprano. Algunos de los defectos de código más comunes que soluciona la refactorización son:
- Código inflado (bloater): Se refiere a código que ha crecido de manera excesiva y se ha vuelto difícil de entender y mantener. Por ejemplo, es el caso de un código con clases o métodos demasiado largos, un exceso de comentarios o una excesiva cantidad de parámetros en funciones.
- Código duplicado: Ocurre cuando hay fragmentos de código que se repiten en diferentes partes del programa, lo que causa problemas de mantenimiento, ya que cualquier cambio en una instancia duplicada requeriría cambios en todas las demás instancias.
- Código obsoleto: Se refiere a partes del código que ya no se utilizan o son redundantes debido a cambios en los requisitos del software o a la evolución del diseño. La refactorización elimina o actualiza este código para mantener la base de código limpia y funcional.
- Clases con demasiadas funciones: Esto ocurre cuando una clase tiene un número excesivo de métodos, lo que indica una violación del principio de responsabilidad única. En la refactorización, se dividen estas clases en clases más pequeñas y cohesivas, cada una con una responsabilidad clara y limitada.
- Nombres de funciones y variables confusos: Nombres poco descriptivos o ambiguos que dificultan la comprensión del propósito o la funcionalidad de una función o variable. En la refactorización, se renombran estas entidades de manera que reflejen mejor su propósito de cara a posteriores modificaciones.
- Comandos go-to: El uso de instrucciones de salto incondicional, como goto, puede hacer que el flujo del programa sea difícil de seguir y comprender. Este comando se utiliza para que el sistema salte de un código a otro que están apartados entre sí, obviando el código de en medio. Una técnica de refactorización consiste en reescribir el código para utilizar estructuras de control más legibles y estructuradas, como bucles y estructuras condicionales.
- Varios comandos if concatenados: Ocurre cuando hay múltiples declaraciones if anidadas o encadenadas, lo que dificulta significativamente la comprensión del flujo de control y llevar a errores lógicos. Para ello, se simplifican estas estructuras a lo largo del proceso de refactorización utilizando técnicas como la reestructuración condicional para que el código resulte más claro y breve.
Ejemplo de refactorización de código
Este código que te presentamos debajo tiene dos funciones separadas para calcular el área y el perímetro de un rectángulo, lo que resulta muy redundante.
Código defectuoso y redundante
def calcular_area_rectangulo(base, altura):
# Calcular el área del rectángulo
resultado = base * altura
return resultado
def calcular_perimetro_rectangulo(base, altura):
# Calcular el perímetro del rectángulo
resultado = 2 * (base + altura)
return resultado
base_rectangulo = 5
altura_rectangulo = 3
area = calcular_area_rectangulo(base_rectangulo, altura_rectangulo)
print("Área del rectángulo:", area)
perimetro = calcular_perimetro_rectangulo(base_rectangulo, altura_rectangulo)
print("Perímetro del rectángulo:", perimetro)
Código refactorizado
En este código refactorizado, creamos una clase Rectangulo que encapsula las propiedades y comportamientos relacionados con un rectángulo. Esto hace que el código sea más modular, reutilizable y fácil de entender. Ahora, las funciones para calcular el área y el perímetro están encapsuladas dentro de la clase Rectangulo, haciendo que el código resulte más claro.
class Rectangulo:
def __init__(self, base, altura):
self.base = base
self.altura = altura
def calcular_area(self):
# Calcular el área del rectángulo
return self.base * self.altura
def calcular_perimetro(self):
# Calcular el perímetro del rectángulo
return 2 * (self.base + self.altura)
# Creamos un objeto Rectangulo con la base y altura dadas
rectangulo = Rectangulo(5, 3)
# Calculamos y mostramos el área del rectángulo
print("Área del rectángulo:", rectangulo.calcular_area())
# Calculamos y mostramos el perímetro del rectángulo
print("Perímetro del rectángulo:", rectangulo.calcular_perimetro())