Why DRY can be misleading

Isaac Cummings
3 min readAug 7, 2018

--

“sepia photography of bare trees” by Dikaseva on Unsplash

DRY, the software design principle that gets so much press. Its listed on every resume, mentioned in every tutorial, it has the power to make developers refactor code just by mentioning its name. One of the reasons DRY is so popular is because of how simple the concept is. Its easy enough to understand that it can be taught on day 1 of a programming career. Most of the time removing duplicate code is the right thing to do, however let’s look at why you may want to reconsider blindly removing that repetitious code.

Suppose you have a data access method that looks like :dal.Get<Foo>(foo => foo.name == “Some Name”) then you might have another part of your application that wants to get foos that have the same name. These instances could be in completely separate areas of the application, but DRY indicates that you should try to build a common function so that you don’t have duplicate code. DRY may lead you to come up with something like this:

public List<Foo> GetFoosByName(string fooName) 
{
return dal.Get<Foo>(foo => foo.name == fooName);
}

Whats interesting about this to me, is that you have just ‘de-abstracted’ your data access. In order to keep things consistent you will now need many data access functions that are specific that call into a more generic way of accessing data. This is a simple example that may seem obvious at first, but imagine if instead of just getting a foo by name, the passed in expression was much more complicated:

dal.Get<Foo>(foo => 
foo.name == "SomeName"
&& foo.value == 45
&& foo.SomeOtherProperty == "SomeOtherValue");

There would come a point when someone would say “Hey we have this 3 line expression in 5 parts of the code, lets make one function that does this”. But the principle still applies. This specific query expression is contextual to this spot in the application.

Its important to be able to identify coincidences

At this point one should ask themselves “Is this repetition a coincidence?”. The answer to that question could identify the next steps. For example, if your 5 spots in the application that get the exact same data are actually very similar forms providing very similar business functions, there is probably a higher abstraction that can be made. Creating a new business logic component that gets the data and then performs whatever operations are similar could be appropriate. However if the areas where this duplicate code exists are indeed just coincidentally similar, its probably best to leave it alone.

An example of coincidental similarity is, two forms where one gets the foos by name in order to present them to the user, and the other gets the foos by name in order to identify duplicate names to satisfy a business rule. In this scenario, creating a common function that both scenarios can call into is somewhat dangerous. It could be possible that one day your duplicate check will include another field, at this point you would have a problem because you cant change the common function since it used in other areas of the application.

Most of the time reusing code rather than duplicating code is the right thing to do. However, using the phrase Don’t Repeat Yourself, can be misleading because there are cases where repeating yourself is not a bad thing. Instead of thinking about whether the code is repeating, we should be thinking about the context and the business scenario. Business logic should be reused whenever possible, but sometimes there will be coincidental similarities in business logic functions that can be left alone.

I hope you enjoyed the post, please let me know what you think in the comments section!

--

--

Isaac Cummings

I’m a software developer, architect and otherwise average guy. I believe we learn the most through writing, and teaching.