Refactorización de código legacy en C#: guía completa de la A a la Z

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Refactorización de código legacy en C#: de la A a la Z



Trabajar con código heredado (legacy) es una realidad inevitable para cualquier desarrollador .NET. Los proyectos antiguos en C# a menudo contienen "código espagueti", números mágicos, clases enormes y falta de pruebas. En lugar de reescribir todo desde cero (lo cual es costoso y arriesgado), una refactorización adecuada permite mejorar el código gradualmente, reduciendo la deuda técnica. En este artículo, analizaremos una estrategia paso a paso para la refactorización de código legacy en C# con ejemplos concretos.



1. Preparación para la refactorización: la seguridad ante todo



La regla principal de la refactorización de código legacy es no romper lo que funciona. Sin pruebas, cualquier cambio puede provocar errores en producción. Por lo tanto, la primera etapa es crear una "red de seguridad".



1.1. Adición de pruebas (Characterization Tests)

Si no hay pruebas, hay que escribirlas. Utilice el enfoque de Characterization Tests (pruebas de caracterización). La idea: ejecuta el código existente con diferentes datos de entrada y registra el comportamiento actual como referencia.



// Ejemplo para un método legacypublic class LegacyCalculator{    public int CalculateTotal(int a, int b)    {        // Código legacy que no entendemos completamente        return a + b * 2; // Lógica sospechosa    }}

// Prueba de caracterización[Test]public void CalculateTotal_WhenCalled_ReturnsCurrentBehavior(){ var calc = new LegacyCalculator(); int result = calc.CalculateTotal(3, 4); // Registramos el resultado actual como esperado Assert.AreEqual(11, result); // 3 + 4*2 = 11}


Después de escribir estas pruebas, puede refactorizar con confianza, sabiendo que las pruebas detectarán regresiones.



1.2. Aislamiento de dependencias

El código legacy a menudo está fuertemente acoplado a la base de datos, el sistema de archivos o servicios externos. Utilice Extract Interface e inyección de dependencias (DI) para aislarlo.



// Antes: dependencia rígidapublic class OrderProcessor{    private readonly SqlDatabase _db = new SqlDatabase();        public void Process(Order order)    {        _db.Save(order);    }}

// Después: interfaz y DIpublic interface IOrderRepository{ void Save(Order order);}

public class OrderProcessor{ private readonly IOrderRepository _repository; public OrderProcessor(IOrderRepository repository) { _repository = repository; } public void Process(Order order) { _repository.Save(order); }}


2. Técnicas principales de refactorización de código legacy en C#



Después de la preparación, se puede proceder a mejorar el código. Aquí están las técnicas clave que funcionan con proyectos .NET.



2.1. Extract Method (Extraer método)

Los métodos enormes con más de 200 líneas son un clásico del código legacy. Divídalos en métodos pequeños y legibles.



// Antes de la refactorizaciónpublic void ProcessInvoice(Invoice invoice){    // 50 líneas de cálculo de descuento    decimal discount = 0;    if (invoice.Total > 1000) discount = 0.1m;    else if (invoice.Total > 500) discount = 0.05m;    // ... mucho más código        // 30 líneas de envío de email    // ... }

// Después de la refactorizaciónpublic void ProcessInvoice(Invoice invoice){ decimal discount = CalculateDiscount(invoice.Total); SendInvoiceEmail(invoice);}

private decimal CalculateDiscount(decimal total){ if (total > 1000) return 0.1m; if (total > 500) return 0.05m; return 0;}

private void SendInvoiceEmail(Invoice invoice){ // Lógica de envío}


2.2. Replace Magic Numbers with Constants

Los números mágicos hacen que el código sea confuso. Reemplácelos con constantes.



// Maloif (user.Role == 3) { /* admin */ }

// Buenopublic enum UserRole{ Guest = 1, User = 2, Admin = 3}

if (user.Role == (int)UserRole.Admin) { /* admin */ }

Blogs

Book Recommendations