DEV Community

Anjan Shrestha
Anjan Shrestha

Posted on

The DRY Principle in Programming: Why It’s Not Always the Best Approach

As developers, we’ve all heard of the DRY principle—“Don’t Repeat Yourself” principle. It’s one of the foundational concepts in programming that encourages reducing code duplication to make our programs more maintainable, efficient, and less error-prone. But here is the thing: While DRY is a valuable principle, there are times when following it too strictly can actually make our code complicated and reduce readability and harder to understand.

In this blog post, we’ll understand when applying DRY might be wrong, and how to apply the right balance between reusing code and keeping it simple to understand.

🚀 Example 1: Greeting Message

Let us explore with a simple scenario:

We have to create a greeting message for users based on the time of day. The message will change depending on whether it’s morning, afternoon, or evening.

Without DRY:

We will create three separate functions, one for each condition by keeping it simple and clear.

For example:

// for morning
function greetingMorningMessage(name: string): string {
  return `Good morning, ${name}!`;
}

// for afternoon
function greetingAfternoonMessage(name: string): string {
  return `Good afternoon, ${name}!`;
}

// for evening
function greetingEveningMessage(name: string): string {
  return `Good evening, ${name}!`;
}
Enter fullscreen mode Exit fullscreen mode

These functions are straightforward and each of them handles different cases.

Applying DRY:

Now, let us try to follow the DRY principle. We might decide to combine three different functions into a single function on the basis of an additional parameter called “timeOfDay.”

For example:

type TimeOfDay = 'morning' | 'afternoon' | 'evening';

function greetMessage(name: string, timeOfDay: TimeOfDay): string {
  if (timeOfDay === 'morning') {
    return `Good morning, ${name}!`;
  } else if (timeOfDay === 'afternoon') {
    return `Good afternoon, ${name}!`;
  } else {
    return `Good evening, ${name}!`;
  }
}
Enter fullscreen mode Exit fullscreen mode

Great, we didn’t repeat our code. But, did we simplify things?

📚 The Lesson:

The original approach (i.e., without the DRY principle) was clearer and more explicit. The DRY version is great, but it requires an extra parameter (i.e., “timeOfDay”) that might not be useful, and we have to pass it every time we call the function.

Sometimes duplicating code for the sake of clarity can be the better approach, especially when the logic is simple and doesn’t need to be generalized.

🚀 Example 2: Age Calculation

Now, let us explore a simple scenario where applying DRY makes perfect sense. We will calculate the age of a person on the basis of their birth year. Let us consider there are two roles: students and teachers.

Without DRY:

We will write separate functions for each role:

interface Student {
  name: string;
  birthYear: number;
}

interface Teacher {
  name: string;
  birthYear: number;
}

function calculateStudentAge(student: Student): number {
  const currentYear = new Date().getFullYear();
  return currentYear - student.birthYear;
}

function calculateTeacherAge(teacher: Teacher): number {
  const currentYear = new Date().getFullYear();
  return currentYear - teacher.birthYear;
}
Enter fullscreen mode Exit fullscreen mode

Now, let us think, Can we combine these two functions into a single function?

  • “Yeah! We can. Let’s do it!”

Applying DRY:

interface User {
  name: string;
  birthYear: number;
}

function calculateAge(user: User): number {
  const currentYear = new Date().getFullYear();
  return currentYear - user.birthYear;
}

const student: User = { name: 'Anjan', birthYear: 2003 };
const teacher: User = { name: 'Sajak', birthYear: 2002 };

console.log(calculateAge(student)); // Student's age
console.log(calculateAge(teacher)); // Teacher's age
Enter fullscreen mode Exit fullscreen mode

📚 The Lesson:

Here, we applied the DRY principle, which simplifies our code by removing duplication. A single function can handle all user types, making our code simpler and increasing readability.

🎯 Conclusion:

The DRY principle is powerful and great, but it has its own drawbacks. Reusing code is great, but it shouldn’t affect clarity, simplicity, or flexibility of the code. There are definitely times when repeating code makes more sense rather than abstracting it.

So what is the key takeaway?

Balance is crucial. The DRY principle is used to reduce duplication of code, but don’t be afraid to duplicate code when it leads to simpler and cleaner code.

In the end, programming is all about solving problems. Sometimes, repeating code might be the simplest solution and avoid unnecessary complexity and over-engineering. After all, clarity and simplicity always win.

Have you over-engineered any solutions while trying to follow the DRY principle? Share your experience in the comments below! 👇

Top comments (0)