Aikido

Cómo eliminar la duplicación de código: reduciendo la deuda técnica

Error lógico

Regla
Elimine obvio dentro del archivo dentro de un archivo.
Duplicado código bloques aumentan mantenimiento
mantenimiento y el riesgo de inconsistentes inconsistentes.
Idiomas compatibles: 45+

Introducción

El código copiado y pegado dentro de un único archivo genera pesadillas de mantenimiento que se agravan con el tiempo. Cuando la misma lógica aparece en varios lugares, las correcciones de errores y las actualizaciones de características deben aplicarse a cada una de las ocurrencias. Los desarrolladores inevitablemente omiten uno de los duplicados, lo que lleva a un comportamiento inconsistente donde la misma operación produce resultados diferentes según la ruta de código que se ejecute. Esta inconsistencia es difícil de depurar porque la lógica duplicada parece idéntica a primera vista, y las diferencias solo emergen después de una comparación cuidadosa.

Por qué es importante

Propagación de errores: Cuando un error existe en código duplicado, corregirlo en una ubicación no lo corrige en todas partes. Los desarrolladores corrigen la primera ocurrencia sin darse cuenta de que existen copias en otros lugares, dejando el error activo bajo diferentes condiciones.

Carga de mantenimiento: Cada bloque duplicado duplica el coste de mantenimiento. Cambiar la lógica requiere encontrar y actualizar cada copia, y a medida que los archivos crecen, el seguimiento de los duplicados se vuelve más difícil.

Ejemplos de código

❌ No conforme:

class OrderProcessor {
    async processStandardOrder(order) {
        if (!order.items || order.items.length === 0) {
            throw new Error('Order must have items');
        }
        const total = order.items.reduce((sum, item) => 
            sum + (item.price * item.quantity), 0);
        const tax = total * 0.08;
        const finalAmount = total + tax;
        return { total: finalAmount, tax };
    }
    
    async processExpressOrder(order) {
        if (!order.items || order.items.length === 0) {
            throw new Error('Order must have items');
        }
        const total = order.items.reduce((sum, item) => 
            sum + (item.price * item.quantity), 0);
        const tax = total * 0.08;
        const expressfee = 15.99;
        const finalAmount = total + tax + expressFee;
        return { total: finalAmount, tax, expressFee };
    }
}

Por qué está mal: La lógica de validación y el cálculo total están duplicados. Si la tasa de impuestos cambia o la validación necesita mejoras, ambos métodos requieren actualizaciones. Un desarrollador podría actualizar el cálculo de impuestos en un método pero olvidarse del otro, causando precios inconsistentes.

✅ Conforme:

class OrderProcessor {
    validateOrder(order) {
        if (!order.items || order.items.length === 0) {
            throw new Error('Order must have items');
        }
    }
    
    calculateSubtotal(items) {
        return items.reduce((sum, item) => 
            sum + (item.price * item.quantity), 0);
    }
    
    calculateTax(amount) {
        return amount * 0.08;
    }
    
    async processStandardOrder(order) {
        this.validateOrder(order);
        const subtotal = this.calculateSubtotal(order.items);
        const tax = this.calculateTax(subtotal);
        return { total: subtotal + tax, tax };
    }
    
    async processExpressOrder(order) {
        this.validateOrder(order);
        const subtotal = this.calculateSubtotal(order.items);
        const tax = this.calculateTax(subtotal);
        const expressFee = 15.99;
        return { total: subtotal + tax + expressFee, tax, expressFee };
    }
}

Por qué es importante: La lógica de validación, cálculo e impuestos está centralizada en métodos únicos. Cambiar el tipo impositivo significa modificar un solo método, no buscar duplicados en el archivo. Cada método auxiliar puede probarse de forma independiente, y ambos tipos de pedido heredan automáticamente cualquier mejora o corrección de errores.

Conclusión

La duplicación dentro de un archivo suele ser la más fácil de corregir y proporciona beneficios inmediatos. Extrae la lógica duplicada en funciones o métodos auxiliares tan pronto como detectes el patrón. La regla de tres sugiere que una vez que el código aparece tres veces, es hora de refactorizar. No esperes a que la duplicación se extienda por todo el archivo antes de abordarla.

Preguntas frecuentes

¿Tiene preguntas?

¿Cuánta duplicación es aceptable antes de refactorizar?

La regla de tres es una buena pauta: una vez que un código similar aparece tres veces, extráigalo. Sin embargo, use el criterio. Dos bloques duplicados complejos podrían justificar una extracción inmediata, mientras que tres declaraciones de variables simples podrían no hacerlo. Considere la probabilidad de cambio y el coste de la inconsistencia. La lógica crítica para la seguridad o las reglas de negocio complejas deben ser desduplicadas inmediatamente.

¿Qué pasa si el código duplicado tiene pequeñas variaciones?

Parametrice las diferencias. Si dos bloques de código difieren solo en los valores de las variables, páselos como parámetros a una función compartida. Si el flujo lógico difiere ligeramente, utilice el patrón de estrategia o parámetros opcionales con valores predeterminados sensatos. A veces, la duplicación con diferencias claras es mejor que una abstracción compleja que oscurece la intención, así que equilibre los principios DRY con la legibilidad.

¿Debería extraer la duplicación incluso si alarga el código?

Normalmente, sí. Una función con un nombre descriptivo a menudo clarifica la intención mejor que el código duplicado en línea, incluso si el recuento total de líneas aumenta. Los beneficios de un mantenimiento en un único punto superan las preocupaciones por la brevedad. Sin embargo, si la extracción crea una indirección excesiva donde la lectura del código requiere saltar a través de múltiples llamadas a funciones, reconsidere si la abstracción es apropiada.

¿Cómo identifico código duplicado en archivos grandes?

Busca patrones de copiar y pegar, como condiciones `if` repetidas, bucles idénticos o estructuras de función similares. Muchos IDEs resaltan la duplicación estructural. Durante la revisión de código, si encuentras código familiar mientras lees un archivo, búscalo. La inspección manual suele ser la más rápida para la duplicación dentro del mismo archivo. Al refactorizar, comienza con los duplicados más obvios que aparecen juntos en el archivo.

¿Qué pasa con el código duplicado de manejo de errores?

Abstrae la gestión de errores en funciones reutilizables o utiliza patrones de decoradores/middleware. Si varias funciones comparten la misma estructura try-catch con un registro y transformación de errores idénticos, es una duplicación que merece la pena eliminar. Crea utilidades de gestión de errores que envuelvan las operaciones con un registro consistente, reintentos o comportamiento de fallback, y luego utiliza esas utilidades en lugar de repetir la lógica de gestión de errores.

¿Vale la pena refactorizar la duplicación en código heredado que no estoy modificando activamente?

Aplica la regla del boy scout: deja el código más limpio de lo que lo encontraste, pero no refactorices código que no estés tocando. Si estás modificando una función y detectas duplicidad dentro del mismo archivo, corrígela como parte de tu cambio. No crees grandes PRs de refactorización para código legado a menos que la deuda técnica esté bloqueando nuevas funcionalidades. La mejora incremental durante el desarrollo normal es más sostenible.

¿Cómo evito la duplicación en primer lugar?

Antes de copiar y pegar código, pregúntate si deberías extraer una función en su lugar. Durante la revisión de código, señala los patrones duplicados y solicita su extracción. Establece convenciones de equipo que desalienten la duplicación, como exigir funciones auxiliares para operaciones repetidas más de dos veces. Utiliza listas de verificación de revisión de código que busquen específicamente la duplicación. La prevención es más fácil que la remediación.

Asegúrate ahora.

Proteja su código, la nube y el entorno de ejecución en un único sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No se requiere tarjeta de crédito | Resultados del escaneo en 32 segundos.