Principio DRY en C#: Por qué la duplicación de código está dañando su base de código - Explicado por Derek Comartin
Cuando hablamos de escribir código mantenible en C#, un concepto fundamental que suele aparecer es el principio DRY - Don't Repeat Yourself (No te repitas). Se trata de un pilar del desarrollo de software cuyo objetivo es eliminar redundancias, reducir la duplicación de código y mejorar su mantenimiento.
Pero, al igual que muchos principios de diseño, DRY puede malinterpretarse e incluso aplicarse incorrectamente. En su vídeo "DRY principle is why your codebase sucks?", Derek Comartin de CodeOpinion.com ofrece una mirada sincera y pragmática sobre cómo debe y no debe utilizarse el principio DRY, especialmente cuando se desarrolla en .NET Core o ecosistemas similares.
En este artículo, profundizaremos en las explicaciones de Derek, repasando sus ejemplos y comentarios del vídeo. Tanto si estás empezando un nuevo proyecto en Visual Studio, como si estás manteniendo una base de código existente o simplemente refactorizando para mejorar la reutilización del código, las ideas de Derek son prácticas y relevantes.
Definición del principio DRY
Al principio del vídeo, Derek enmarca el contexto al que se enfrentan muchos desarrolladores: enfrentarse a un sistema difícil de modificar, una maraña de código repetido y lógica redundante.
Introduce el principio DRY en C# como estrategia para reducir la repetición de código, pero advierte de que a menudo se malinterpreta. Como explica Derek en el minuto 0:28:
"Cuando DRY se aplica con éxito, una modificación de cualquier elemento individual del sistema no requiere un cambio en ningún elemento lógicamente no relacionado."
Esta distinción es fundamental. El principio DRY tiene como objetivo no sólo evitar la duplicación de código, sino también promover la separación de preocupaciones y la reutilización adecuada del código, lo que conduce a un código seco y fácil de mantener que es más fácil de probar y refactorizar.
Ejemplo práctico: Conversión de distancias
Para hacer las cosas tangibles, Derek ofrece un ejemplo sencillo en C#. Escribe dos métodos:
-
Distancia del barco
- Distancia de peaje
Cada una calcula las distancias en millas y luego las convierte en kilómetros, utilizando la misma lógica en ambos métodos. Se trata de la clásica duplicación de código.
En lugar de tener el mismo fragmento de código en varios lugares, Derek muestra cómo se podría extraer la lógica de conversión en un método privado - MilesToKilometers() - una forma básica pero eficaz de refactorizar el código para su reutilización.
Para ilustrarlo, utiliza la estructura típica de una aplicación de consola: una clase Program con un void estático Main. Es el tipo de estructura que muchos desarrolladores utilizan cuando prueban la lógica o experimentan con un nuevo escenario de entrada de usuario como public int age, string username, string password, etc.
DRY vs. Sobreacoplamiento
Aunque abstraer la lógica en un método reutilizable o en una clase separada suena ideal, Derek pide precaución. El uso excesivo de DRY, especialmente en toda una aplicación, puede conducir a niveles peligrosos de acoplamiento.
Por ejemplo, si se coloca la lógica de conversión en una utilidad compartida utilizada por varios proyectos y más tarde se cambia su comportamiento de redondeo o la precisión decimal, el cambio podría afectar inesperadamente a muchas áreas. Como dice Derek en el minuto 2:31:
"¿Esperan los clientes dos decimales? ¿Qué pasa si lo cambiamos a cero?"
Se trata de una preocupación transversal -lógica reutilizada por muchas partes del sistema- e ilustra el riesgo de centralizar demasiado pronto o sin límites claros.
Los consejos de Derek aquí se hacen eco del Principio de Responsabilidad Única y del Principio de Inversión de Dependencia, otros dos principios SOLID fundamentales para mantener tu código adaptable y modular.
Code Bloat de DRY Gone Wrong
Otro problema derivado del uso incorrecto de DRY es la sobrecarga del código, ya que intentar abstraerlo todo da lugar a clases de utilidad sobrecargadas o métodos demasiado genéricos. Derek advierte que una lógica demasiado seca puede causar más daño que ayuda, especialmente en grandes sistemas donde la corrección de errores en un área puede romper otras debido a las dependencias compartidas.
La clave, según Derek, es saber cuándo no hay que compartir código, sobre todo si el resultado son módulos muy acoplados. DRY no es una regla; es una guía que debe utilizarse con contexto.
DRY aplicado a entidades: Una receta para la complejidad
Derek identifica una tendencia común de los desarrolladores: organizar los sistemas enteramente en torno a entidades como Truck, Order, Driver y Shipment. Aunque es tentador reutilizar la misma clase u objeto en diferentes métodos, esto a menudo conduce a la repetición de conceptos y a acoplamientos no deseados.
Sostiene que las capacidades empresariales -no solo las estructuras de datos- deben impulsar la arquitectura. Por ejemplo, "enviar un pedido" es un asunto diferente de "desenganchar un remolque", aunque se trate de las mismas entidades.
A las 4:45, Derek explica:
"Una entidad singular en su sistema no necesita ser una representación de múltiples conceptos"
Esto pone de relieve una idea arquitectónica más profunda: entidades con el mismo nombre (vehículo, remolque) pueden representar diferentes responsabilidades en diferentes flujos de trabajo. Utilizarlas indistintamente crea confusión y vincula estrechamente lógicas de negocio no relacionadas.
Desarrollo y capacidades empresariales
Para resolver este problema, Derek presenta la Arquitectura de Cortes Verticales (VSA), un patrón que estructura las aplicaciones en torno a capacidades empresariales en lugar de capas. Cada "porción" incluye todo lo necesario para una acción o caso de uso específico, desde la solicitud hasta la base de datos, encapsulado y autocontenido.
Destaca que el código DRY es bueno dentro de una rebanada -dentro de una única ubicación-, pero aplicar DRY a través de rebanadas puede conducir a dependencias enredadas. A las 6:44, añade:
"Se trata simplemente de reducir el acoplamiento, aumentar la cohesión... y una forma de hacerlo es: no repetir conceptos dentro de un mismo límite"
Esta forma de pensar basada en los límites le aporta flexibilidad. Puede que tengas un modelo de dominio completo en una parte y sólo un modelo de datos ligero en otra. Se trata de un enfoque pragmático alineado con la filosofía de The Pragmatic Programmer.
Reflexiones finales
Derek concluye reenmarcando DRY como una herramienta, no una ley. Como dice a las 7:00
"Se trata de entender cómo se aplica. Si lo aplicas mucho, potencialmente tienes más acoplamiento"
Así que antes de extraer esa lógica de validación, cadena de conexión, o convertir código repetitivo en un método separado, considere si hacerlo realmente hará que toda su base de código sea más mantenible - o simplemente más difícil de cambiar.
Conclusión
El desglose de Derek Comartin del principio DRY en C# muestra cómo una regla aparentemente sencilla puede ser contraproducente si se aplica sin matices. A través de ejemplos de código, situaciones prácticas y principios de diseño de software, revela el equilibrio necesario entre reutilización y modularidad.
Para mejorar significativamente su proceso de desarrollo, recuerde:
-
Utilice DRY para refactorizar el código redundante dentro de unos límites claros.
-
No hay que secar entidades que sirven a diferentes fines empresariales.
-
Respete el contexto al centralizar la lógica, especialmente en varios lugares o proyectos.
- Hay que tener en cuenta las pruebas unitarias y cómo la inyección de dependencias puede afectar al código compartido.
Aplicando estas lecciones, escribirá código C# más eficiente, modular y fácil de mantener, y evitará convertir su base de código en un nido de ratas de lógica duplicada y dependencias enmarañadas.
Puedes ver el vídeo completo de Derek Martin video para más información en CodeOpinion's YouTube channel.
