Don't Repeat Yourself (DRY)

Written by Reinder de Vries on April 12 2019 in App Development

Don't Repeat Yourself (DRY)

Don’t Repeat Yourself (DRY) is a principle in software development that helps you reduce the amount of repetition in your code and apps. This has a number of advantages, for example, code that’s easier to maintain.

In this article we’ll discuss what the Don’t Repeat Yourself principle is and how it works. We’ll focus on DRY at the code level, but also moisture levels between components, app projects, and even people. (No more jokes about moisture, I promise.)

The core question we’re going to discuss is: “Should you never repeat code, or is there a balance to be struck?” Let’s get to it!

  1. What is DRY?
  2. DRY In Writing Code
  3. DRY In iOS Development
  4. The Perfect Level Of DRYness
  5. Further Reading

What is DRY?

The Don’t Repeat Yourself, also known as “DRY”, was first formulated by Andy Hunt and Dave Thomas in their must-read book for developers, The Pragmatic Programmer.

DRY is defined as:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

Like any good definition, it’s a bit cryptic, so let’s discuss it further by making use of a metaphor.

Imagine that you’re putting together an encyclopedia. You’re writing pages on famous persons, animals, how a car engine works, and so on. It’s an extensive, comprehensive encyclopedia that includes relevant knowledge for today’s age.

Quick question: Would you include the entry about the Sun, i.e. the star at the center of our solar system, twice? Why not?

What a stupid question. Of course you wouldn’t duplicate that page and include it twice in the encyclopedia. The idea of an encyclopedia is that it discusses every topic once. An encyclopedia topic is singular, unambiguous and has authority.

OK, next question: Would you include a paragraph that discusses what a star is, i.e. a big sphere of plasma that shines a bright light in space, in the Sun or Astronomy or Solar system chapters? If you put it in Astronomy, would you consider writing a helpful aside for the Sun chapter that briefly explains what a Sun is?

And there it is: repetition. You’re now repeating part of the discussion about stars in the Sun chapter, next to writing about stars more extensively in the chapter about Astronomy.

What if you have to change the entry about stars? Because of the repetition, you now have to edit the encyclopedia in two places. Stars don’t change that much fortunately, so for encyclopedias change isn’t such a bad thing.

In iOS development, change happens every day. A client’s or employer’s needs and wants, your understanding of a better workflow, or refactoring – software changes constantly. New requirements get added, which can change the architecture and flow of your app.

You can imagine that, if you’ve written the same code in two places, maintaining and updating that code takes more time and effort than it would have if you had coded it once.

This is the argument in favor of DRY: not repeating code is easier to maintain, which is more productive than writing code twice. It also leads to less errors, because you can’t forget to update the repeated code.

Let’s look at some practical scenarios for Don’t Repeat Yourself, next.

Become a professional  iOS developer

Get started with iOS 13 and Swift 5

Sign up for our iOS development course Zero to App Store to learn iOS development with Swift 5, and start with your professional iOS career.

DRY In Writing Code

Imagine you’re building your app’s User Interface (UI) with Swift code. You want to add 3 buttons to the view. Once you coded one button, you copied that code and used it as a prototype for the other two buttons.

You end up with something like this:

let button1 = UIButton(type: .custom)
button1.setTitle("Log In", for: .normal)
button1.addTarget(self, action: #selector(onLoginButtonTapped(_:)), for: .touchUpInside)

let button2 = UIButton(type: .custom)
button2.setTitle("Sign Up", for: .normal)
button2.addTarget(self, action: #selector(onSignupButtonTapped(_:)), for: .touchUpInside)

let button3 = UIButton(type: .custom)
button3.setTitle("Log In With Facebook", for: .normal)
button3.addTarget(self, action: #selector(onLoginFacebookButtonTapped(_:)), for: .touchUpInside)

See what’s going on here? We’ve created 3 buttons, but 90% of code is the same. Moreover, we also have 3 functions (for the actions) that probably share a fair amount of business logic.

How can we improve the code? Here’s an idea:

let buttons = ["Log In", "Sign Up", "Log In With Facebook"]

for title in buttons
{
    let button = UIButton(type: .custom)
    button.setTitle(title, for: .normal)
    button.addTarget(self, action: #selector(onButtonTapped(_:)), for: .touchUpInside)

    view.addSubview(button)
}

You could call the above for loop a generator. Instead of hard-coding the 3 buttons, you use a data structure and iterate over it to generate the 3 buttons.

The above code uses hardly any fewer lines of code (9 vs. 6), but it’s much easier to maintain. If you want to change the button’s appearance, you only have to change one line of code instead of three.

Problems arise, however, if you want to change only one of the buttons. Say the first button has a different color than the other two. Do you add this as a value to the buttons array? Do you flatten the iteration back to individual statements?

Those questions get to the core of DRY. How much DRYness is appropriate? We’ll discuss that by the end of this article.

Author’s Note: In general, I’m a fan of clarity over cleverness. If you’ve created a data structure that cleverly generates buttons, you might just be writing too much code. A simple line-by-line block to create the buttons is clearer. The Rule of Three – “Three strikes and you refactor” – can help here, too.

DRY In iOS Development

The Don’t Repeat Yourself principle doesn’t just affect code itself. You also find it in computer systems, documentation, and even communication between developers.

A few examples:

  • You’ve coded a complex algorithm. In the code itself, you describe how the algorithm works with code comments. You also give a high-level overview of the algorithm in the software’s written documentation. You might inadvertently repeat knowledge between those 3 places!
  • A colleague of yours decide to set up a webserver for an in-company, browser-based project management tool. Some time later, you set up a webserver for a similar purpose; an in-company realtime chat tool. You didn’t know you already had a webserver, so now you have two webservers to maintain…
  • Your company develops social media apps. These apps need some code to parse, filter and structure hashtags. Guess what? Two developers in the same company wrote similar code to parse these hashtags! Wouldn’t it have been better to create a shared library for helper functions?

In many cases it’s impossible to get around duplication. The web-based project management tool might generate a heavier load on the webserver, so you decide to run one compute-intensive webserver, and a lighter one. In any case, some communication between developers needs to occur before you can get an insight like that.

Should you write comments to describe how an algorithm works? Maybe, maybe not. The code should (but doesn’t always) explain itself. It might be a good idea to describe the algorithm in a docblock. You can then generate documentation based on the docblocks (with Jazzy), and link to it in the main documentation.

In general, good communication can resolve or help avoid problems with DRY. You can write code in such a way that it’s reusable by other developers. You can discuss how you can better share resources within the company. And you can use smart tools, like generators, to avoid hard-coding the same thing twice.

The opposite of DRY is, half-jokingly, “WET”: Write Everything Twice.

The Perfect Level Of DRYness

It’s dangerous to adopt software development principles without understanding how they work. You might end up doing code acrobatics just for the sake of not repeating your code. This will likely not make your code easier to maintain.

  • Do you think MVC always stands for Massive View Controller?
  • Are you against using singletons, but don’t know exactly why?
  • Does your company use agile, because it’s afraid to create behemoths of software projects?
  • Do you use microservices because someone – you forgot who – said monoliths are bad?
  • Do you swear by reactive programming, because everyone is using it – and everyone can’t be wrong?

You might suffer from cargo cult software development, and that’s perfectly alright. For some time in your software development career, you will want to follow what other people are doing. It’s a great way to learn!

Extreme views, such as “Singletons are bad”, help you shape your views about using singletons. You’ll hopefully begin to understand that using singletons wrong, is wrong. You might conclude that it’s easy to misuse singletons, and be more cautious in using them.

This is a balance, and it’s no different with the Don’t Repeat Yourself principle. Avoiding repetition too much can push you towards writing highly dependent and coupled code. Repeating code too much can lead to apps that are hard to maintain and error-prone.

So, the perfect level of DRYness doesn’t exist. It’s more like a balance – a balance that’s informed by your understanding of iOS development and insights into what makes great code. And that insight starts by asking good questions.

† A cargo cult, a term I first heard about from Richard Feynman, is best explained as imitating a more advanced culture or practice in the hope of attaining the benefits or wealth from those cultures, without understanding the root cause of the benefits or wealth. Agile, reactive or microservices don’t exclusively produce great software. So, what does? Curiosity, and asking the right questions, helps you avoid cargo cult thinking.

Further Reading

Don’t repeat yourself! It’s the DRY principle, and it’s important in iOS development and Swift programming. Make your code too DRY, and it becomes “cleverness over clarity”. Make your code too WET, and you’ll create code that’s hard to maintain.

Want to learn more? Check out these resources:

Reinder de Vries

Reinder de Vries

Reinder de Vries is a professional iOS developer. He teaches app developers how to build their own apps at LearnAppMaking.com. Since 2009 he has developed a few dozen apps for iOS, worked for global brands and lead development at several startups. When he’s not coding, he enjoys strong espresso and traveling.