Tuple Logo
don't-repeat-yourself-dry

SHARE

Don't Repeat Yourself (DRY)

DRY, or “Don’t Repeat Yourself,” is a core principle in software development that emphasizes that every piece of knowledge or logic should exist in only one place within a system. The goal is straightforward: eliminate repetition. While this might seem obvious at first, duplication often creeps into codebases, especially as projects grow and complexity.

The DRY principle was first introduced in The Pragmatic Programmer by Andrew Hunt and David Thomas. They argued that duplication is the root of many maintenance and scalability issues in software. When logic or data is repeated across different parts of the code, there’s a high risk that updates made in one place are forgotten in others, leading to bugs and inconsistent behavior.

DRY isn’t just about code elegance or style; it’s a practical guideline that helps keep software understandable, flexible, and reliable.

What is DRY?

DRY stands for Don't Repeat Yourself, and it's a principle in software development that encourages you to avoid duplication, whether in code, logic, documentation, or configuration. The idea is that every piece of knowledge in a system should have a single, unambiguous, authoritative representation.

A well-known definition from The Pragmatic Programmer puts it like this:

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

In simple terms: if a piece of logic already exists somewhere, don’t write it again somewhere else. If that logic ever changes, you’d need to update every copy, which is time-consuming, error-prone, and hard to maintain.

DRY goes beyond just code

Although the principle is most often applied to code, DRY thinking also applies to:

So, DRY isn’t a coding trick, it’s a mindset. The key question is: Where else does this logic or information live, and how can I centralize or reuse it?

Why is DRY important?

The DRY principle is crucial because duplication creates problems, especially as projects grow and multiple developers start working on the same codebase. Below are the key reasons why DRY plays such an important role in professional software development.

1. Fewer bugs and errors

When the same logic is duplicated in multiple places, there's a high risk that one instance will be missed during an update. Imagine a calculation being repeated in five different files. If the rules change, each instance needs to be updated. Forgetting just one can cause inconsistent behavior in your application.

By applying DRY, you centralize that logic. This means changes only need to happen in one place, significantly reducing the risk of errors.

2. Easier maintenance

DRY code is easier to maintain. Developers spend less time searching through files and understanding scattered logic because everything is centralized. This results in faster updates, quicker debugging, and more readable codebases.

3. More efficient teamwork

In a team environment, DRY prevents developers from duplicating each other's work or reinventing the wheel. Once a piece of logic is implemented properly, others can reuse it instead of rewriting it from scratch.

4. Better scalability and reusability

DRY encourages the use of reusable components, functions, or modules. This makes it easier to add new features without having to rewrite or break existing code. As the project grows, your codebase stays manageable and consistent.

Real-world example

Let’s say you’re building a form that checks if an email address is valid. In a non-DRY approach, the validation logic might be copied into every form. In a DRY approach, you create one reusable validation function and use it across all forms. That saves time, avoids bugs, and makes maintenance much easier.

Common scenarios where DRY is needed

While the DRY principle makes perfect sense in theory, duplication still sneaks into codebases in many real-world situations. Below are some of the most common scenarios where applying DRY can make a big difference.

Shared business logic

A classic example of duplication is business logic – like calculating taxes, discounts, or shipping fees – appearing in multiple parts of an application. If that logic is hardcoded in several places, updates become risky and time-consuming.

Solution: Move the logic into a single shared function or service module.

Front-end components

In modern front-end frameworks like React or Vue, it’s easy to repeat UI elements such as buttons, form fields, or cards with slight variations.

Solution: Create reusable components that accept props or parameters to customize behavior and style.

Configuration files

Configuration settings are often copied between environments (development, staging, production). If a value changes in one file and not the others, it can lead to inconsistencies and hard-to-trace bugs.

Solution: Use centralized config files, shared constants, or environment variables (e.g. .env files).

SQL queries or database logic

In large applications, it’s common to see the same queries or joins written over and over again. If your data model changes, all these places need to be manually updated.

Solution: Use stored procedures, views, or an ORM (like Prisma, Sequelize, or Hibernate) to centralize data access logic.

CSS or styles

Without structure, CSS files can become bloated with duplicate styling rules. This is especially common in teams with multiple developers or in legacy codebases.

Solution: Use utility-first CSS (like Tailwind), component-scoped styles, or SCSS variables and mixins to keep styles DRY.

How to resolve duplication with DRY

Fixing duplication starts with recognizing repeating patterns in your code or configuration. Once identified, you can reduce or eliminate them using a few common techniques, depending on the type of project and where the repetition occurs.

Abstract shared logic

One of the most effective ways to apply DRY is to extract repeating logic into functions, methods, classes, or modules.

Example:

// Repetitive code
const priceWithTax1 = price1 * 1.21;
const priceWithTax2 = price2 * 1.21;

// DRY approach
function calculateTax(price) {
  return price * 1.21;
}

This eliminates duplication, makes your code easier to read, and allows for simpler changes, like updating the tax rate in one place only.

Use automation

Many repetitive tasks can be handled through automation. Examples include:

By automating standard processes, you avoid manual repetition and keep logic consistent across different environments.

Normalize data

In databases, DRY is often achieved through normalization. This means separating data into related tables so each piece of information exists in just one place. Without normalization, you risk storing the same customer data in multiple locations, leading to inconsistencies.

Example of poor structure:

OrderIDCustomerIDCustomerName (redundant)
1011John Smith

Improved (normalized):

Customer table:

CustomerIDName
1John Smith

Order table:

OrderIDCusomterID
1011

This ensures your data is consistent, easier to manage, and DRY-compliant.

Comparison with other approaches

While DRY is a powerful principle, it’s not a one-size-fits-all solution. In some cases, repeating code can be the better option, especially in early-stage projects or when abstraction introduces unnecessary complexity. There are alternative approaches that sometimes make more sense depending on the situation.

WET – Write Everything Twice

WET is often seen as the opposite of DRY. It stands for Write Everything Twice or jokingly, “We Enjoy Typing.” The idea is that repetition can be acceptable in certain phases of development, such as:

Pros: Quick to write, low mental overhead.

Cons: If left unchecked, duplication can quickly turn into a maintenance nightmare.

AHA – Avoid Hasty Abstractions

AHA offers a more flexible take on DRY. It stands for Avoid Hasty Abstractions. This approach encourages developers to hold off on abstraction until it’s absolutely necessary.

Imagine you see two very similar functions. The instinct might be to merge them immediately. But if their differences grow over time, the shared abstraction could become messy and hard to maintain.

AHA suggests: wait until the duplication is clear, consistent, and worth abstracting.

Summary comparison:

Advantages and disadvantages of DRY

The DRY principle is widely embraced, and for good reason. But like any principle, it comes with potential drawbacks. In this section, we’ll explore when DRY works well and when it might work against you.

Advantages

Less maintenance and fewer bugs

When logic exists in only one place, you only need to update it once. This reduces the risk of inconsistencies and unexpected behavior across your application.

Improved readability and structure

DRY encourages you to break down code into clear, reusable blocks. This makes it easier for teammates (and your future self) to understand what’s going on.

Reusable components

Thinking DRY naturally leads to creating reusable functions, modules, or components. That means faster development in the future, and less code overall.

Easier to test

Well-isolated and centralized logic is much easier to test. DRY helps ensure your business rules live in one place, making unit testing more focused and effective.

Disadvantages and challenges

Premature abstraction

One common mistake is abstracting too early, combining pieces of code that only seem similar. This often results in overly complex functions with lots of parameters or conditionals.

Reduced readability

Overusing DRY can make code harder to read. In some cases, duplicating a small line or two might actually improve clarity, especially in scripts or simpler logic.

Harder to debug

If your logic is buried in abstract layers or helper modules, debugging can take longer. You might need to jump through multiple files to track down a bug.

Collaboration issues

Not everyone will understand your abstraction the same way. Overly generic solutions can clash with how others expect to read or expand the codebase.

DRY vs other principles

While DRY is a powerful guideline, it's just one of many principles in software development. It’s often used alongside other design principles, but understanding how they differ – and where they overlap – is key to writing clean, maintainable code.

DRY vs Single Responsibility Principle (SRP)

The Single Responsibility Principle (SRP) states that a module, class, or function should have only one reason to change, in other words, it should do one thing. DRY is about avoiding duplication, while SRP is about clear separation of concerns.

Although different in focus, the two principles complement each other. Applying DRY without considering SRP can lead to bloated utility functions that do too much. On the other hand, applying SRP without DRY may result in multiple classes or modules repeating similar logic.

DRY vs KISS (Keep It Simple, Stupid)

KISS emphasizes simplicity, don’t make things more complex than necessary. While DRY encourages abstraction, KISS warns against overengineering and making things harder to understand.

A good DRY implementation should still honor KISS. But if you apply DRY too early, you may violate KISS by creating generic but overly complex helpers to eliminate just a small amount of repetition.

The key is balance: use DRY to reduce duplication, but keep things as simple and readable as possible.

Tips for applying DRY

The DRY principle sounds simple, but in practice, it requires thoughtful execution. Below are practical tips to help you apply DRY effectively, without falling into the trap of over-abstraction.

Make reuse easy

If code is hard to reuse, developers are more likely to copy and paste it. To encourage reuse, make sure your functions and modules:

Avoid premature decisions

When you spot duplication, the instinct is often to abstract it immediately. But not all repetition needs to be eliminated right away. Sometimes it's better to accept duplication temporarily and only refactor when a clear pattern emerges.

Rule of thumb: if the same logic shows up in three places, it’s probably time to abstract it.

Consider context and your team

What seems like a logical abstraction to you might be confusing to someone else. Communicate changes clearly when introducing shared helpers or modules. Make sure your team understands why something is structured a certain way.

Combine DRY with other principles

DRY works best when used in harmony with other development principles, such as:

When combined properly, these principles help you write code that is not only reusable, but also readable and maintainable.

Don't repeat yourself unnecessarily

The DRY principle – Don’t Repeat Yourself – helps developers reduce duplication and keep software organized, reliable, and scalable. By ensuring that logic, data, and configuration exist in only one place, you reduce errors, simplify maintenance, and improve team collaboration.

However, DRY requires balance. Applying it too early or too aggressively can lead to confusing abstractions and unnecessary complexity. When combined with other principles like SRP (Single Responsibility Principle), KISS (Keep It Simple, Stupid), and AHA (Avoid Hasty Abstractions), DRY becomes part of a healthy development mindset.

In short: DRY is not a rule set in stone but a practical guideline. Don’t repeat yourself unnecessarily, but also don’t be afraid to break the pattern when simplicity or clarity calls for it.

Frequently Asked Questions
What does don't repeat yourself mean?

Don't Repeat Yourself (DRY) is a software principle that states every piece of logic or knowledge in a system should exist in only one place to prevent duplication.


Why should you not repeat yourself?

Repeating logic increases the risk of bugs, inconsistencies, and maintenance issues. DRY helps create reusable, cleaner, and more reliable code.


Why is DRY code bad sometimes?

Overusing DRY or abstracting too early can make code harder to read, maintain, and debug. It’s important to apply it with context and balance.


Articles you might enjoy

Piqued your interest?

We'd love to tell you more.

Contact us
Tuple Logo
Veenendaal (HQ)
De Smalle Zijde 3-05, 3903 LL Veenendaal
info@tuple.nl‭+31 318 24 01 64‬
Quick Links
Customer Stories