Why the DRY principle isn't always the right answer

The Don't Repeat Yourself (DRY) principle is a core design pattern across the whole spectrum of Software Development and the Web Industry is no exception.

Whilst a great principle to follow, there are times where the trade off from this workflow outweighs it's benefits and it's those moments that I see developer's struggle with time and again.

When do you follow the DRY principle and when do you decide it's not fit for purpose?

In this post I'll aim to answer exactly that. As a refresher for you veterans and an introduction for those of you not familiar, I'll go over the intricacies of the pattern to understand what it is and why it's so useful, and then provide examples in order to determine why the principle shouldn't be used in all scenarios.

What is the Don't Repeat Yourself (DRY) principle?

As the title may suggest, DRY revolves around removing repetition in your projects. Whilst not the case for all situations, generally we look for the best possible product with the least amount of code. The more code we have, the longer it will take to operate, which increases code complexity, decreases maintainability and eventually reduces performance on the whole.

It's the decision of "should I, shouldn't I" that is a constant struggle for developers new and old and one that DRY aims to solve.

The Don’t Repeat Yourself (DRY) principle states that duplication in logic should be eliminated via abstraction; duplication in process should be eliminated via automation.

By committing to this philosophy, you will be providing your projects with some significant benefits that far outweigh the hand-strain from writing out the same thing twice (although wrists have feelings too!), these include...

Project fragility

Splitting code into separate files (also known as Abstraction) ensures that any references to the same functionality are housed in one central location. Should you need to change that piece of code then you only need to update it in one place, rather than having to manually update every reference throughout your project. This is a common practice in Software Development called the Single Source of Truth (SSOT).

We can utilise this idea of SSOT in many different ways, even in how we organise our CSS code using more modular techniques such as Object Orientated CSS, BEM and SMACSS. Example time!

Going to the popular Web Design publication, Smashing Magazine, you'll see a number of components on their website. For this demonstration I'm interested in two:

Author component: Shown at the bottom of blog posts to credit the author of the post.

Sidebar promotions: Seen in the right-hand sidebar for advertisements.

Fig 1: Screenshot of the author component on the Smashing Magazine website.

Fig 2: Screenshot of the promotional sidebar component on the Smashing Magazine website.

Whilst these components are visually different, structurally they are very similar and can ultimately be built from the same foundations. They both feature the idea of an image floating to the left of text, so we can tackle both of these instances with one module, the media object.

Note: These examples will be responsive so take a look at the desktop view for the desktop view, etc

Rather than duplicating our code twice, we can use these classes in conjunction with others to create the differences we see in our Author and Sidebar Promotions components, such as: positioning, colours, sizing and more.

This is one way where the DRY principle can shine, rather than creating new classes for our two components and repeating our code, we're reusing what we already have, essentially halving our code.

Cost efficiency

Writing less code is a natural money saver as your time can be spent on other areas of your applications. Going back to the previous example on our CSS components, if we're saying that one component takes 10 minutes of time to build, then building both of them from scratch could take double that. Of course, this is only a small example, but applying this principle to a more complex situation can help solidify it's importance.

An example might be a blog that requires a date formatting. On this blog the date is formatted in two places, on the listing and post pages.

Using the Carbon DateTime extension for PHP, we can create a new instance of the class and then echo out the correctly formatted date.

Instead of duplicating our code like this, we can create a universal date formatting function that can be used throughout our application, even for future uses of dates that are not currently implemented.

In addition, we've also continued the flexibility of our code by not assuming that every date uses the same format. By allowing for the format to be set when using the function you're not pushing yourself or other developers into a hole to climb out of should you need to change this at a later date.

Reasons not to use the principle

So you may be thinking that the DRY principle rocks. Let's use it everywhere!? No! As with everything in web development, there are pros and cons. Let's take a look at the cons.

Code complexity

If not left unchecked code abstraction can leave a project susceptible to a form of the very thing we're trying to avoid - technical debt.

Technical debt is a concept in programming that reflects the extra development work that arises when code that is easy to implement in the short run is used instead of applying the best overall solution.

Cool, so that's going to reduce our bytes a little, especially compressed, which in a large application may save us a few KB. However, there are side effects.

The first is that our code is harder to read. A new developer coming onto the project will need to ensure that they know which components are using this new class, requiring them to look in HTML files rather than just the CSS and increasing risk as things may be missed.

The second is that we've dug ourselves into a corner. In order to reduce file sizes by a few bytes we're now assuming that all .btn, .promotion and .author components will always have the same padding and background color. If this ever changes, then you'll likely be increasing the source code to add a new version of this, or have to remove that completely altogether.

Before abstracting your code first ask yourself whether or not you're abstracting because of coincidence or because the functionality is supposed to be the same. In addition, weigh up the benefits. What are you actually gaining from doing this? If it's a few bytes, would the developer uptake on this abstraction not suffer? Would time not be better spent in other areas?

Unfortuantely there's no right or wrong answers with these concepts. Principles by nature are not set is stone and therefore should not be followed 100% of the time. By asking whether or not we should do something, we can save the project from future technical debt moving forward; future you will be grateful.

If there's one thing I hope you take from this it's that there is a trade off between abstraction and maintainability that needs to be weighed up at all times. Principles are set of guidelines to follow when possible, not a set of rules we must adhere to at all times.

Luke Whitehouse

Hi Matthew,

Thanks for getting in touch, I did reply to your comment on Reddit but I'll copy that reply here for anyone else too.

"The main reason was that I wanted to make sure the post was as accessible as possible to everyone, even people not familiar with certain technologies. I'm a very strong advocate of Sass and the methodologies I listed in the post such as BEM and OOCSS but I didn't feel it was necessary to add them in here as I wanted the post to be for more people than just Front-end Developers."

Stelian Andrei

"Principles are a set of guidelines to follow when possible, not a set of rules we must adhere to at all times"

This is probably the main thing people should keep in mind after reading this. I've often found myself over-optimizing things to later find out that a bit of repetition gives way for more flexibility in the future.
However, don't interpret this as "repeat everything so you have full flexibility". The DRY principle still stands, but, as the article says, there are situations when you should put it aside, based on your own needs and requirements