Aikido

Cómo eliminar la duplicación de código: reducir 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 mismo archivo crea 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 funciones deben aplicarse a cada caso. Inevitablemente, los desarrolladores pasan por alto uno de los duplicados, lo que provoca un comportamiento incoherente en el que la misma operación produce resultados diferentes en función de la ruta de código que se ejecute. Esta incoherencia es difícil de depurar porque la lógica duplicada parece idéntica a primera vista, y las diferencias sólo surgen tras una cuidadosa comparación.

Por qué es importante

Propagación de errores: Cuando un fallo existe en código duplicado, arreglarlo en un sitio no lo arregla en todos. Los desarrolladores arreglan la primera incidencia sin darse cuenta de que existen copias en otros lugares, lo que deja el fallo activo en condiciones diferentes.

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 crecen los archivos, el seguimiento de los duplicados se hace más difícil.

Ejemplos de códigos

❌ 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é es incorrecto: La lógica de validación y el cálculo del total están duplicados. Si el tipo impositivo cambia o la validación necesita una mejora, 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 validación, el cálculo y la lógica fiscal están centralizados en métodos únicos. Cambiar el tipo impositivo significa modificar un método, no buscar duplicados en el archivo. Cada método de ayuda se puede probar 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 solucionar y proporciona beneficios inmediatos. Extraiga la lógica duplicada en funciones o métodos de ayuda en cuanto detecte el patrón. La regla de tres sugiere que una vez que el código aparece tres veces, es hora de refactorizar. No espere a que la duplicación se extienda por todo el archivo antes de abordarla.

Preguntas frecuentes

¿Tiene alguna pregunta?

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

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

¿Y si el código duplicado tiene pequeñas variaciones?

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

¿Debo extraer la duplicación aunque alargue el código?

Por lo general, sí. Una función con un nombre descriptivo suele aclarar mejor la intención que el código inline duplicado, aunque aumente el número total de líneas. Las ventajas del mantenimiento en un único punto son mayores que la preocupación 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 el código duplicado en archivos grandes?

Busque patrones de copia y pega como condiciones if repetidas, bucles idénticos o estructuras de función similares. Muchos IDE destacan la duplicación estructural. Durante la revisión del código, si ve código familiar mientras lee un archivo, búsquelo. La inspección manual suele ser más rápida para detectar la duplicación dentro de un mismo archivo. Cuando refactorice, empiece por los duplicados más obvios que aparezcan juntos en el archivo.

¿Qué ocurre con el código de gestión de errores duplicado?

Extraiga la gestión de errores en funciones reutilizables o utilice patrones de decoradores/middleware. Si varias funciones comparten la misma estructura try-catch con idéntico registro y transformación de errores, es una duplicación que merece la pena eliminar. Cree utilidades de gestión de errores que envuelvan las operaciones con un registro coherente, reintentos o comportamientos alternativos y, a continuación, utilice dichas utilidades en lugar de repetir la lógica de gestión de errores.

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

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

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

Antes de copiar y pegar código, pregúntese si debería extraer una función en su lugar. Durante la revisión del código, señale los patrones duplicados y solicite su extracción. Establezca convenciones de equipo que desincentiven la duplicación, como exigir funciones auxiliares para operaciones que se repitan más de dos veces. Utilice listas de comprobación de revisión de código que busquen específicamente la duplicación. Prevenir es más fácil que remediar.

Asegúrese gratis

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

No requiere tarjeta de crédito | Escanea resultados en 32segs.