DRY no es (sólo) lo que piensasDRY Isn’t (Only) What You Think

Seguramente DRY fuera una de los primeros principios de desarrollo de software de los que oíste hablar. Imagino que mientras programabas al lado de algún compañero copiaste y pegaste un bloque de código y éste te dijo algo así como: “¡Oye! Eso va en contra de DRY. No te repitas. Don’t Repeat Yourself!”. O viste un artículo en internet y, claro, con ese acrónimo tan pegadizo se te quedó grabado en el cerebro.
Y así venía a tu mente cada vez que veías el mismo código varias veces o tenías la tentación de copiar y pegar. Y así lo transmitiste siempre que viste una ocasión.
Así al menos fue para muchos de nosotros. Y al empezar a programar es genial tener reglas tan claras de lo que está bien y está mal, de lo que se debe y no se debe hacer. Pero según ganas conocimientos y experiencia te das cuenta de que nada es universal, correcto o incorrecto, blanco o negro. Que las líneas son difusas y que nada es tan fácil como parece, incluyendo DRY.
Hoy quiero escribir de por qué creo que DRY es mucho más de lo que habitualmente se piensa, y de que no trata de ti, no trata sobre repetir, ni siquiera se trata de código, y no siempre es “no”.
Un momento, ¿qué es DRY?
DRY viene del acrónimo “Don’t Repeat Yourself” y es uno de los principios de desarrollo más extendidos. Fue acuñado por Andy Hunt y Dave Thomas en su libro The Pragmatic Programmer, uno de los libros que siempre recomiendo leer a todo desarrollador.
DRY surge de los peligros de duplicar el conocimiento, lo que implica que ante un cambio debemos acordarnos de todos los lugares donde duplicamos ese conocimiento o caeremos en inconsistencias en nuestro sistema. El principio completo es:
Toda pieza de conocimiento debe tener una única, precisa y completa representación dentro de un sistema.
Si nos quedamos con el principio completo tendremos una idea mucho más clara de lo que representa DRY, pero si tan sólo nos quedamos con el acrónimo nos perderemos muchos matices que nos harán simplificar en exceso de que trata.
DRY no trata sobre ti
Cuando trabajas solo todo resulta bastante sencillo. Comienzas un proyecto y lo vas haciendo crecer. Así es fácil darse cuenta cuando, de repente, tienes la misma necesidad que hace un rato o unos días y necesitas usar el mismo código. Entonces te dices a ti mismo: “Recuerda. DRY. Don’t Repeat Yourself”. Así que abstraes la lógica, refactorizas para llamar al mismo código desde los diferentes puntos tu código y sigues tu proyecto con la satisfacción del que consigue hacer las cosas bien hechas.
Pero cuando te incorporas a un equipo te das cuenta que la cosa se complica. Ya no sirve con que estés atento a no repetir el código que hiciste hace unos días, sino que también debes tener en cuenta el código de tus compañeros. Y tus compañeros deben tener en cuenta el código que tú estás haciendo. De nada sirve que cada miembro del equipo no se repita a sí mismo, si todos acaban repitiendo lo mismo entre ellos.
Y es que como tan bien dice esa frase hecha en inglés: There’s no I in TEAM. Y cuando sois muchos programando, el problema deja de ser repetir y empieza a ser trabajar en equipo.
Por ello es importante saber comunicar qué estás haciendo, qué necesitas, y que tus compañeros hagan lo mismo. Saber compartir el conocimiento importante para que todo el equipo sea consciente de él. Y documentar de forma efectiva para que el conocimiento llegué a todos, incluso a los compañeros que aún no están trabajando contigo y que puede que ni siquiera te lleguen a conocer.
También es importante tener en cuenta el Principle of Least Astonishment, algo así como el principio de la mínima sorpresa, para que cuando seas tú el que desarrolles algo que creas que puede ser útil para los demás, lo situes en el lugar dónde tus compañeros esperen encontrarlo y se comporte exactamente como ellos esperan.
DRY no trata sobre repetir
Lo mismo pasa cuando llegas a un proyecto grande, con miles de líneas de código y muchos años en desarrollo. En tu pequeño proyecto era fácil darte cuenta de las repeticiones pero… ¿cómo sabes si estás repitiendo algo si no conoces el proyecto en el que trabajas?
Para saberlo necesitas conocer el código fuente del proyecto y las convenciones que se han usado en él. Cómo se estructura, qué módulos tiene, dónde se encuentran las funciones de utilidad, qué convención de nombrado usan… para así poder buscar lo que necesitas antes de programarlo.
Y debes saber bien qué es lo que estás buscando. Aquí no sólo sirve el conocimiento específico de tu proyecto, sino el conocimiento general y profundo sobre desarrollo de software. ¿Lo que estás buscando tiene un nombre concreto que corresponde a un patrón de diseño? ¿Un tipo de algoritmo? ¿Una estructura de datos? ¿Un concepto extendido en programación? Puesto que para buscar algo tienes que saber ponerle nombre.
Y por último, también debes saber cómo buscar. Pues cuando trates con proyectos grandes, de nada sirve saber qué buscar si tienes que hacerlo manualmente entre miles de ficheros. Por ello también es importante dominar las herramientas de búsqueda de tu IDE o comandos de terminal como find y grep para encontrar aquello que buscas.
DRY no trata sobre repeticiones
Si esto te sonaba algo confuso, aquí se complica aún más. Porque realmente DRY no trata sobre repeticiones, sino sobre patrones y abstracciones.
Puede haber código repetido que no incumpla DRY y código que a simple vista parezca muy diferente que esté incumpliendo este principio.
Habrá casos donde encontremos código que es igual de una manera casual, pero que está claro que va a evolucionar de forma diferente. Aquí sería un error extraer el código común. O casos donde el código parezca diferente, por como está nombrado y estructurado, pero que esconda el mismo patrón. En este caso deberemos abstraerlo. Y es que la clave de DRY es identificar un patrón y generalizarlo con el nivel de abstracción idóneo para que sea útil para todos nuestros casos. Ni uno más, ni uno menos.
Aquí se crean diferentes líneas de pensamiento a DRY, como WET (Write Everything Twice) o variantes que nos dicen que debemos esperar a repetir el mismo código N veces antes de abstraerlo para evitar precipitarnos. Personalmente no lo comparto ya que lo veo demasiado rígido. Habrá veces que desde un primer momento se tenga claro cuál es el patrón y podamos abstraerlo. Y otras que aún repetido 5 veces no terminemos de ver claro si se trata del mismo patrón o cuál es el nivel correcto de abstracción y sea preferible esperar a tener más conocimiento.
Lo que es importante es darse cuenta de los peligros de la abstracción prematura y que muchas veces duplicar código es preferible antes que crear la abstracción incorrecta. Sandi Metz lo explica mucho mejor que yo en este artículo que os recomiendo leer.
DRY no trata sobre código
Aunque cuando hablamos de DRY solemos hablar sobre código, no sólo aplica al código, como tan bien expresaron Andy Hunt y Dave Thomas , si no que lo tendremos que tener en cuenta para todo el conocimiento que tengamos representado en nuestro sistema, ya sea código, configuración, documentación…
Debemos tener este principio en cuenta y tomar las medidas necesarias para evitar que el conocimiento se duplique y podamos caer en contradicciones entre diferentes fuentes o partes del sistema.
DRY no siempre es no
Por último, aún habiendo encontrado la repetición, teniendo claro el patrón y el nivel de abstracción correcto, puede que a veces entren en juego otros factores que nos indiquen que no es una buena idea aplicar DRY.
Por ejemplo, cada vez que extraes un código común estás creando una dependencia entre distintas partes de tu sistema y/o entre distintos equipos. Por ello habrá que analizar si esta dependencia tiene sentido y merece la pena con los posibles problemas que puede conllevar.
También es probable que al extraer este código común debas hacerlo público en forma de API para que sea usado por diferentes módulos y/o equipos. Aquí estarás atado a mantener el contrato de tu API para no romper el código de otros equipos o clientes que puedan estar usándolo, y por ello debes estar muy convencido de que es la abstracción correcta, o sino será preferible esperar hasta estar más seguro como hemos comentado antes.
Por estas razones y otras fuera del código puede que no siempre sea una buena idea no duplicar código.
Más allá de DRY
Con este artículo quería mencionar habilidades y principios relacionados con DRY que creo que muchas veces pasamos por alto.
Pero más allá de DRY, creo que es necesario seguir remarcando que no existe un principio o patrón universal que podamos aplicar siempre, por muy sencillo o lógico que parezca. Siempre habrá ventajas y desventajas según el contexto en el que estemos y nuestro deber es hacer análisis y balance para aplicar la solución adecuada en cada caso.
Espero que te haya resultado interesante y, si te apetece, ¡seguimos la conversación por las redes!

DRY was probably one of the first software-development principles you ever heard about. I imagine that while you were programming next to some colleague you copied and pasted a block of code and they told you something like: “Hey! That goes against DRY. Don’t repeat yourself. Don’t Repeat Yourself!”. Or you saw an article online and, of course, with such a catchy acronym it stuck in your brain.
And so it came to mind every time you saw the same code several times or were tempted to copy and paste. And so you passed it on whenever you saw the chance.
That, at least, is how it went for many of us. And when you’re starting out it’s great to have such clear rules about what’s right and what’s wrong, about what you should and shouldn’t do. But as you gain knowledge and experience you realize that nothing is universal, right or wrong, black or white. That the lines are blurry and that nothing is as easy as it seems, including DRY.
Today I want to write about why I believe that DRY is much more than what people usually think, and that it isn’t about you, isn’t about repeating, isn’t even about code, and isn’t always “no”.
Hold on, what is DRY?
DRY comes from the acronym “Don’t Repeat Yourself” and it’s one of the most widespread development principles. It was coined by Andy Hunt and Dave Thomas in their book The Pragmatic Programmer, one of the books I always recommend every developer read.
DRY arises from the dangers of duplicating knowledge, which means that in the face of a change we have to remember all the places where we duplicated that knowledge or we’ll fall into inconsistencies in our system. The full principle is:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
If we keep the full principle in mind we’ll have a much clearer idea of what DRY represents, but if we only keep the acronym we’ll miss many nuances that lead us to oversimplify what it’s about.
DRY isn’t about you
When you work alone everything turns out to be quite simple. You start a project and you keep growing it. That way it’s easy to notice when, suddenly, you have the same need you had a while ago or a few days back and you need to use the same code. Then you say to yourself: “Remember. DRY. Don’t Repeat Yourself”. So you abstract the logic, refactor to call the same code from the different points in your code, and carry on with your project with the satisfaction of someone who manages to do things well.
But when you join a team you realize that things get complicated. It’s no longer enough to be careful not to repeat the code you wrote a few days ago; you also have to take your colleagues’ code into account. And your colleagues have to take into account the code you’re writing. It’s no use for each team member not to repeat themselves if they all end up repeating the same thing among themselves.
And as that English saying so aptly puts it: There’s no I in TEAM. And when there are many of you programming, the problem stops being about repeating and starts being about working as a team.
That’s why it’s important to know how to communicate what you’re doing, what you need, and to have your colleagues do the same. To know how to share the knowledge that matters so the whole team is aware of it. And to document effectively so the knowledge reaches everyone, even the colleagues who aren’t working with you yet and who may never even get to know you.
It’s also important to keep the Principle of Least Astonishment in mind, so that when you’re the one developing something you think might be useful for others, you place it where your colleagues expect to find it and have it behave exactly as they expect.
DRY isn’t about repeating
The same thing happens when you arrive at a large project, with thousands of lines of code and many years in development. In your small project it was easy to spot repetitions but… how do you know whether you’re repeating something if you don’t know the project you’re working on?
To know that you need to know the project’s source code and the conventions used in it. How it’s structured, what modules it has, where the utility functions live, what naming convention they use… so you can look for what you need before programming it.
And you must know well what it is you’re looking for. Here it isn’t just the specific knowledge of your project that helps, but the general and deep knowledge about software development. Does what you’re looking for have a specific name that corresponds to a design pattern? A type of algorithm? A data structure? A widespread concept in programming? Because to search for something you have to know how to name it.
And finally, you must also know how to search. Because when you deal with large projects, it’s no use knowing what to search for if you have to do it manually across thousands of files. That’s why it’s also important to master your IDE’s search tools or terminal commands like find and grep to find what you’re looking for.
DRY isn’t about repetitions
If this sounded a bit confusing, here it gets even more complicated. Because DRY really isn’t about repetitions, but about patterns and abstractions.
There can be repeated code that doesn’t break DRY, and code that at first glance looks very different yet is breaking this principle.
There will be cases where we find code that is the same by coincidence, but where it’s clear it’s going to evolve differently. Here it would be a mistake to extract the common code. Or cases where the code looks different, because of how it’s named and structured, but hides the same pattern. In this case we should abstract it. And the key to DRY is to identify a pattern and generalize it with the right level of abstraction so that it’s useful for all our cases. Not one more, not one less.
Here different schools of thought arise in contrast to DRY, like WET (Write Everything Twice) or variants that tell us we should wait to repeat the same code N times before abstracting it to avoid jumping the gun. Personally I don’t agree, since I find it too rigid. There will be times when from the very first moment the pattern is clear and we can abstract it. And others when even after repeating it 5 times we still can’t quite see whether it’s the same pattern or what the right level of abstraction is, and it’s preferable to wait until we have more knowledge.
What’s important is to realize the dangers of premature abstraction and that many times duplicating code is preferable to creating the wrong abstraction. Sandi Metz explains it much better than I do in this article that I recommend you read.
DRY isn’t about code
Although when we talk about DRY we usually talk about code, it doesn’t only apply to code, as Andy Hunt and Dave Thomas expressed so well; rather, we’ll have to keep it in mind for all the knowledge we have represented in our system, whether it’s code, configuration, documentation…
We must keep this principle in mind and take the necessary measures to prevent knowledge from being duplicated and to avoid falling into contradictions between different sources or parts of the system.
DRY isn’t always no
Finally, even after having found the repetition, being clear about the pattern and the right level of abstraction, sometimes other factors may come into play that tell us it isn’t a good idea to apply DRY.
For example, every time you extract common code you’re creating a dependency between different parts of your system and/or between different teams. So you’ll have to analyze whether this dependency makes sense and is worth it given the potential problems it can bring.
It’s also likely that when extracting this common code you’ll have to make it public in the form of an API so it can be used by different modules and/or teams. Here you’ll be bound to maintaining your API’s contract so as not to break the code of other teams or clients that may be using it, and that’s why you have to be very convinced that it’s the right abstraction, or else it will be preferable to wait until you’re more sure, as we discussed earlier.
For these reasons and others outside the code, it may not always be a good idea not to duplicate code.
Beyond DRY
With this article I wanted to mention skills and principles related to DRY that I think we often overlook.
But beyond DRY, I think it’s necessary to keep stressing that there’s no universal principle or pattern we can always apply, however simple or logical it may seem. There will always be advantages and disadvantages depending on the context we’re in, and our duty is to analyze and weigh them to apply the right solution in each case.
I hope you found it interesting and, if you feel like it, let’s keep the conversation going on social media!