Command Palette

Search for a command to run...

Principio DRY en JavaScript: Don't Repeat Yourself

Aprende a aplicar el principio DRY para eliminar duplicación de código y crear aplicaciones más mantenibles y escalables.

Lectura: 13 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • El principio DRY significa Don't Repeat Yourself: cada pieza de conocimiento debe tener una única representación
  • La duplicación de código causa problemas de mantenimiento, bugs y inconsistencias
  • Extrae código duplicado en funciones reutilizables con parámetros apropiados
  • Usa abstracción y patrones de diseño para eliminar duplicación estructural
  • Aplica DRY con criterio: no sacrifies legibilidad por evitar duplicación trivial

Introducción al Principio DRY

El principio DRY (Don't Repeat Yourself) es uno de los fundamentos más importantes de la programación moderna. Enunciado por Andy Hunt y Dave Thomas en The Pragmatic Programmer, establece que cada pieza de conocimiento debe tener una única, inequívoca y autorizada representación dentro de un sistema. En términos prácticos, esto significa evitar la duplicación de código siempre que sea posible.

La duplicación de código es más que un problema estético: es un problema técnico serio que afecta la mantenibilidad, la calidad y la evolución del software. Cuando el mismo código existe en múltiples lugares, cualquier cambio requiere modificaciones en todas esas ubicaciones, aumentando la probabilidad de errores y haciendo el mantenimiento más costoso y propenso a fallos.

  • Reduce el mantenimiento: los cambios se hacen en un solo lugar
  • Disminuye la probabilidad de bugs: menos código que mantener
  • Mejora la consistencia: el mismo comportamiento en todo el sistema
  • Facilita el testing: menos código que probar
  • Aumenta la reutilización: el código está diseñado para ser compartido

¿Qué es el Principio DRY?

El principio DRY establece que cualquier lógica o funcionalidad debe existir en un solo lugar del código. Cuando necesitas esa funcionalidad, la invocas desde ese lugar único en lugar de duplicarla. Esto no significa que no puedas tener código que se parezca visualmente, sino que no debes tener código que implemente la misma lógica o regla de negocio en múltiples lugares.

Tipos de Duplicación

La duplicación puede manifestarse de varias formas: duplicación de código literal, duplicación de lógica con diferente implementación, y duplicación estructural. Cada tipo requiere un enfoque diferente para eliminarla, pero todas violan el principio DRY y deben abordarse sistemáticamente.

tipos-duplicacion.js
Loading code...

El ejemplo muestra tres tipos de duplicación: duplicación literal (el mismo código copiado), duplicación de lógica (misma funcionalidad implementada de forma diferente) y duplicación estructural (el mismo patrón repetido). Cada una de estas debe ser extraída a una función reutilizable que capture la lógica común.

Es importante distinguir duplicación de similitud. No toda similitud es duplicación real: si dos piezas de código se parecen pero sirven propósitos diferentes y evolucionarán independientemente, no necesariamente deben unificarse. DRY se aplica cuando la misma lógica de negocio o funcionalidad se repite en múltiples contextos.

Detectar Duplicación de Código

El primer paso para aplicar DRY es identificar dónde existe la duplicación. Las herramientas de análisis estático de código, el code review y la refactorización continua son prácticas efectivas para detectar duplicación. Los patrones comunes incluyen funciones que hacen casi lo mismo, bloques de código copiados con pequeños cambios, y validaciones repetidas en múltiples lugares.

Patrones Comunes de Duplicación

Hay patrones de duplicación que aparecen frecuentemente en código JavaScript. Reconocer estos patrones te ayudará a identificar oportunidades para aplicar DRY de manera proactiva. Los patrones más comunes incluyen validaciones repetidas, formateo duplicado, y lógica de negocio replicada.

patrones-duplicacion.js
Loading code...

Los ejemplos muestran patrones comunes de duplicación: validación de email en múltiples lugares, formateo de moneda duplicado, y cálculo de precio con impuesto repetido. Cada uno de estos patrones debe extraerse a una función reutilizable que centralice la lógica.

  • <strong>Validaciones repetidas:</strong> La misma validación en múltiples funciones
  • <strong>Formateo duplicado:</strong> El mismo formateo de datos en diferentes lugares
  • <strong>Cálculos repetidos:</strong> La misma fórmula matemática en múltiples contextos
  • <strong>Transformaciones duplicadas:</strong> La misma conversión de datos en varios módulos

Herramientas de Detección

Las herramientas automatizadas pueden ayudarte a detectar duplicación de código de manera sistemática. ESLint con plugins específicos, herramientas de análisis de código como SonarQube, y características de los IDEs modernos pueden identificar duplicación que podría pasar desapercibida durante el code review manual.

eslint-duplicacion.js
Loading code...

Las reglas de ESLint como no-duplicate-imports detectan importaciones duplicadas, mientras que herramientas más avanzadas pueden detectar duplicación de lógica y código. Configurar estas herramientas en tu proyecto ayuda a mantener el principio DRY de manera preventiva, alertándote cuando introduces duplicación involuntaria.

Detección continua

Integra la detección de duplicación en tu pipeline de CI/CD. Herramientas como SonarQube pueden bloquear pull requests que introducen demasiada duplicación, asegurando que el principio DRY se mantenga de manera consistente en todo el equipo.

Extracción de Funciones

La extracción de funciones es la técnica más directa para aplicar DRY. Cuando identificas código duplicado, extrae la lógica común a una función con un nombre descriptivo. Esta función debe recibir parámetros para las partes que varían y devolver el resultado. La clave es que la función capture la intención y la lógica, no solo el código literal.

Extracción Básica

La extracción básica consiste en identificar bloques de código que se repiten y moverlos a una función separada. La función debe tener un nombre que describa claramente qué hace, y recibir como parámetros los valores que varían entre las diferentes instancias del código duplicado.

extraccion-basica.js
Loading code...

El ejemplo muestra cómo extraer validación duplicada a una función reutilizable. En lugar de repetir la misma lógica de validación en múltiples lugares, creamos una función `validarEmail` que encapsula la lógica. Ahora cualquier cambio en la validación de email se hace en un solo lugar.

Extracción de Lógica Compleja

Para lógica más compleja, la extracción puede requerir dividir el código en múltiples funciones más pequeñas, cada una con una responsabilidad específica. Esto no solo elimina duplicación, sino que también mejora la legibilidad y testabilidad del código al descomponer operaciones complejas en pasos más simples.

extraccion-compleja.js
Loading code...

El ejemplo muestra cómo extraer lógica compleja de cálculo de precio en funciones más pequeñas y reutilizables. La función principal `calcularPrecioFinal` compone las funciones auxiliares para calcular el precio con impuestos y descuentos. Cada función auxiliar puede reutilizarse independientemente.

Composición sobre herencia

Al extraer funciones complejas, prefiere la composición de funciones pequeñas sobre crear funciones monolíticas. Las funciones pequeñas son más fáciles de entender, probar y reutilizar en diferentes contextos.

Parametrización

La parametrización es la técnica de convertir valores fijos en parámetros para hacer el código más reutilizable. Cuando tienes código que hace casi lo mismo pero con diferentes valores, esos valores deben convertirse en parámetros de una función. Esto elimina la duplicación mientras mantiene la flexibilidad para manejar diferentes casos.

Parámetros de Configuración

Los parámetros de configuración permiten que una misma función se comporte de diferentes maneras según los valores que recibe. Esto es especialmente útil para validaciones, formateo y operaciones que tienen variaciones predecibles pero consistentes. La clave es identificar qué valores varían y convertirlos en parámetros.

parametrizacion-configuracion.js
Loading code...

El ejemplo muestra cómo parametrizar una función de validación para que sea más flexible. En lugar de tener múltiples funciones de validación para diferentes longitudes, creamos una función que recibe la longitud mínima como parámetro. Esto elimina la duplicación mientras mantiene la flexibilidad.

Parámetros Opcionales y Defaults

Los parámetros opcionales con valores por defecto permiten que una función maneje tanto casos simples como complejos sin duplicación. Los valores por defecto proporcionan comportamiento estándar, mientras que los parámetros opcionales permiten personalización cuando es necesario. Esto reduce la necesidad de múltiples funciones para variaciones similares.

parametros-opcionales.js
Loading code...

El ejemplo muestra cómo usar parámetros opcionales con valores por defecto para crear una función flexible. La función `formatearFecha` tiene un valor por defecto para el locale, pero permite personalizarlo cuando es necesario. Esto evita tener múltiples funciones de formateo para diferentes locales.

Advertencia sobre demasiados parámetros

Evita funciones con demasiados parámetros (más de 4-5). Si necesitas muchos parámetros, considera usar un objeto de configuración que agrupe los parámetros relacionados. Esto mejora la legibilidad y hace más fácil agregar o quitar parámetros sin romper el código existente.

Abstracción y Patrones

Cuando la duplicación es estructural o patrones de diseño se repiten, la extracción simple de funciones no es suficiente. En estos casos, necesitas abstracción: crear estructuras de nivel superior que capturen el patrón común y permitan variaciones específicas. Los patrones de diseño como Strategy, Factory y Template Method son ejemplos de abstracción para eliminar duplicación.

Patrones de Diseño para DRY

Los patrones de diseño proporcionan soluciones probadas para problemas recurrentes de duplicación. El patrón Strategy permite encapsular algoritmos intercambiables, Factory centraliza la creación de objetos, y Template Method define el esqueleto de un algoritmo. Estos patrones eliminan duplicación estructural mientras mantienen la flexibilidad.

patrones-diseño-dry.js
Loading code...

El ejemplo muestra el patrón Strategy para eliminar duplicación en algoritmos de ordenamiento. En lugar de tener múltiples funciones de ordenamiento con lógica duplicada, encapsulamos cada algoritmo en un objeto strategy y tenemos una función que delega en la estrategia apropiada. Esto elimina duplicación estructural.

Abstracción apropiada

La abstracción debe ser apropiada al nivel de complejidad del problema. No sobre-abstraigas código simple, pero tampoco evites abstracción cuando el patrón es claro y repetitivo. El objetivo es eliminar duplicación significativa sin introducir complejidad innecesaria.

Composición de Funciones

La composición de funciones es una técnica poderosa para eliminar duplicación mediante la combinación de funciones pequeñas y reutilizables. En lugar de duplicar lógica compleja, la construyes componiendo funciones simples que cada una hace una cosa bien. Esto crea código más modular, testeable y fácil de entender.

composicion-funciones.js
Loading code...

El ejemplo muestra cómo componer funciones para procesar datos sin duplicación. Las funciones `validar`, `transformar` y `formatear` son pequeñas y reutilizables. La función `procesarUsuario` las compone para crear un flujo completo de procesamiento. Cada función puede reutilizarse independientemente en otros contextos.

Cuándo NO Aplicar DRY

Aunque DRY es un principio importante, no debe aplicarse ciegamente. Hay situaciones donde la duplicación es aceptable o incluso preferible. Aplicar DRY indiscriminadamente puede llevar a código sobre-abstracto, difícil de entender y mantener. El criterio es clave: evalúa si la duplicación es significativa y si la abstracción mejora o empeora el código.

Duplicación Aceptable

Hay casos donde la duplicación es aceptable: cuando el código es trivial y la abstracción añadiría complejidad, cuando las dos instancias evolucionarán independientemente, o cuando la duplicación es accidental y temporal. En estos casos, aplicar DRY puede ser una sobre-optimización que no aporta valor real.

duplicacion-aceptable.js
Loading code...

El ejemplo muestra casos donde la duplicación es aceptable: código trivial como inicializar objetos, configuraciones que evolucionarán independientemente, y código temporal. En estos casos, la abstracción añadiría más complejidad que valor, y es preferible mantener la duplicación simple.

Advertencia sobre sobre-abstracción

La sobre-abstracción es tan peligrosa como la duplicación. Si tu abstracción es más compleja de entender que el código duplicado que reemplaza, probablemente has ido demasiado lejos. La regla de oro: la abstracción debe simplificar, no complicar.

El Principio WET

WET (Write Everything Twice) es el antónimo humorístico de DRY. Sugiere que está bien escribir código dos veces antes de abstraerlo. La idea es que la primera vez es para entender el problema, la segunda para identificar el patrón, y solo entonces abstraer. Esto evita abstracciones prematuras basadas en una sola instancia.

principio-wet.js
Loading code...

El ejemplo muestra el enfoque WET: primero escribes el código dos veces para entender el patrón, luego extraes la abstracción. Esto evita crear abstracciones basadas en una sola instancia que pueden no ser apropiadas cuando aparece una segunda variación.

La "Rule of Three" complementa este enfoque: debes duplicar código hasta tres veces antes de abstraerlo. La primera vez es accidental, la segunda es coincidencia, y la tercera es un patrón que merece abstracción. Esta regla te protege de abstracciones prematuras que complican el código sin aportar valor real.

Resumen: Principio DRY

Conceptos principales:

  • DRY significa Don't Repeat Yourself: cada conocimiento debe tener una única representación
  • La duplicación causa problemas de mantenimiento, bugs e inconsistencias
  • Tipos de duplicación: literal, lógica y estructural
  • Extracción de funciones y parametrización eliminan duplicación básica
  • Abstracción y patrones de diseño eliminan duplicación compleja

Mejores prácticas:

  • Identifica duplicación mediante code review y herramientas de análisis
  • Extrae código duplicado a funciones con nombres descriptivos
  • Usa parámetros para hacer funciones más reutilizables
  • Aplica patrones de diseño para duplicación estructural
  • No sacrifiques legibilidad por DRY: usa el criterio apropiado