Don't make your code too DRY

Thu, Dec 15, 2016 2-minute read

A well known software engineering principle is don’t repeat yourself, often abbreviated as DRY.

The principle was originally formulated in The Pragmatic Programmer:

When the DRY principle is applied successfully, a modification of any single element of a system does not require a change in other logically unrelated elements.

The quote suggests that when everything goes well we can expect to end up with a better codebase. What’s sometimes not well understood is what happens when programmers are overzealous in DRY-ing up their code, even when that’s not the best approach.

When we are in a situation where we can apply DRY we need to choose between two different conflicting outcomes. We can either have:

  • a codebase with totally decoupled modules, albeit with some duplication;
  • a single implementation and have coupling between each module depend on it.

As it usually happens in software engineering, it’s time to decide which side of the trade off we want to take.

If the code does really the same thing and you don’t anticipate the different modules to evolve in a way that will make them use the feature you’re extracting in different ways DRY-ing it up is a good idea. What you’ll obtain is a nice shared function and we can enjoy the benefits of DRY, as presented in the book.

On the opposite, if the functionality you want to share looks similar but is fundamentally different or could evolve in different directions, some duplication might be a better choice. We don’t want to get to the point where the shared code gets overly complex, just because it has to accomodate all the possible scenarios. If I have to choose, the single responsibility principle always wins over don’t repeat yourself.

Even worse, now we have some coupling. This means that every time we need to update the shared function because of a change in the requirements of one of its clients, we could need to update all the other places where we use it. Yes, we could get to the point that in order to have single implementation a modification of single element of a system requires a change in other logically unrelated elements.