dark mode light mode Search Menu

How to Keep Your Code DRY

adactio on Flickr

Here’s how it works in real life. Plus a DRY joke at the end.

Imagine you’re a programmer. Someone has asked you to write code to generate a random number between 1 and 1000. The random number is to be used by another bit of code. You sit down and write simple clean code to generate a random number:

nbr = create_rnd_nbr(1,1000)
print nbr

where create_rnd_nbr is a built in function included in the programming language which expects a start number (1) and end number (1000) to be passed into it. You assign the result of create_rnd_nbr(1,1000) to the variable named nbr then print the variable as a number to your computer screen.

A month passes, you’re busy, and they ask you to write another bit of code to generate a random number between 1 and 500 to be used by another part of the application. You could adapt the code you have to work in both cases, for numbers between 1 and 1000 and 1 and 500. But you’re busy. So you copy paste your oode and change the limit from 1000 to 500:

nbr = create_rnd_nbr(1,1000)
print nbr

new_nbr = create_rnd_nbr(1,500)
print new_nbr

Now you have two blocks of code that generate random numbers.

Imagine this happens a third and fourth time. You have four different blocks of code to generate random numbers. Time passes, you leave the company, and a few years later the company hires a new programmer. Someone has noticed the application generates weird random numbers. They think its the random number code you wrote.

If you’re a new programmer, you might go into the 10,000 lines of code, find where the random number is generated, then test the code, fix any problems, and be done. Perhaps the problem is the built in create_rnd_nbr function provided by the programming language has changed. You’re still learning on the job and there’s not a lot of time. You don’t realize there are three other bits of code in the application to generate random numbers. Perhaps your fix doesn’t completely solve the problem.

If programming is a religion, using the same or almost the same code in multiple places in an application is a sin. It introduces needless complexity and risk of errors.

DRY is an acronym for Don’t Repat Yourself. It is one of the key concepts programmers try to follow as they create code. A good code review session will flag duplicate code and ask the programmer to rewrite their code to work in multiple locations.

Instead of these four blocks of code to generate random numbers:

nbr = create_rnd_nbr(1,1000)
print nbr

new_nbr = create_rnd_nbr(1,500)
print new_nbr

rand_nbr = create_rnd_nbr(100,500)
print rand_nbr

first_nbr = create_rnd_nbr(150,250)
print first_nbr

You would have this one block of code to generate random numbers for any specified range:

do_rand_nbr ( start, end )
	nbr = create_rnd_nbr( start, end )
	return nbr

And here is the code you would use to replace the four nearly idential bloks of code used to generate random numbers:

nbr = do_rand_nbr ( 1, 1000 )

new_nbr = do_rand_nbr ( 1, 500 )

rand_nbr = do_rand_nbr ( 100, 500 )

first_nbr = do_rand_nbr ( 150, 250 )

With DRY, if there is a problem with the way do_rand_nbr ( start, end ) code generates numbers, you only need to fix one location in your code, not four locations.

What happens if you need to pass three values to generate random numbers, not two? For example, you need to call do_rand_nbr like this:

nbr = do_rand_nbr ( 1, 1000, new_third_value )

instead of this call to your code:

nbr = do_rand_nbr ( 1, 1000 )

To add a third value, you would update the one code block:

do_rand_nbr ( start, end, new_third_value )
	nbr = create_rnd_nbr( start, end, new_third_value )
	return nbr

Then you would have to search for all code that calls the do_rand_nbr code block and add the new third value to pass to the do_rand_nbr code to generate a random number:

nbr = do_rand_nbr ( 1, 1000, new_third_value )

new_nbr = do_rand_nbr ( 1, 500, new_third_value )

rand_nbr = do_rand_nbr ( 100, 500, new_third_value )

first_nbr = do_rand_nbr ( 150, 250, new_third_value )

You also could set the new_third_value in your do_rand_nbr code block to equal null by default:

do_rand_nbr ( start, end, new_third_value=null )
	nbr = create_rnd_nbr( start, end, new_third_value )
	return nbr

If there is no third value passed to do_rand_nbr, the code still runs.What works best depends on how the code is supposed to work.

DRY takes extra time to design then write code. But it is time well spent to prevent errors and ensure code is easier to maintain over time. Every serious programmer will make the time.

Also interesting: DRY helps identify edge cases where your code will need to do different things in ways that might not be obvious.

Imagine, for example, fixing the do_rand_nbr code causes problems because, in two cases, the number do_rand_nbr generates doesn’t work with your code. Perhaps a special kind of random number is needed, or a random number is only needed in specific situations in that part of your code. Using the same or similar code in four places might hide this complexity.

Writing a single block of code forces you to write code to identify then account for this hidden complexity. The single block of do_rand_nbr code won’t work in all four places in the application. Without DRY your code might work today but not in a few years. In other words, DRY can make you a better and more efficient programmer.

If you know a real programmer, and want to have a little fun, ask them to tell you what DRY means. When they finish, say “What?” as if you’ve not heard. If they repeat themselves as they explain the concept again, be sure to have a good laugh. And, yes, I know this is an example of dry humor. So it goes.

Learn More



Using DRY: Between Code Duplication and High-Coupling


The DRY Obsession


Orthogonality and the DRY Principle

A Conversation with Andy Hunt and Dave Thomas who developed the term DRY.

Software Design Principles (including DRY)