Skip to main content

Command Palette

Search for a command to run...

DRY Principle in Java – Don’t Repeat Yourself (With Clean Code Examples)

Updated
3 min read
DRY Principle in Java – Don’t Repeat Yourself (With Clean Code Examples)

Introduction

When writing production-level Java applications, code readability and maintainability matter more than just making things work.
One of the most fundamental design principles that helps achieve this is the DRY Principle.

DRY = Don’t Repeat Yourself

The DRY principle states that every piece of knowledge or logic should have a single, unambiguous representation in the system.

In simple terms:
👉 If you copy-paste code, you’re probably violating DRY.


Why DRY Matters in Java Applications

Violating DRY leads to:

  • Hard-to-maintain code

  • Bugs when logic changes

  • Inconsistent behavior

  • Increased technical debt

Following DRY gives you:

  • Reusable components

  • Easier refactoring

  • Cleaner architecture

  • Fewer bugs


DRY Violation Example (Bad Code)

Let’s say we’re calculating discounted price in multiple places.

public class OrderService {

    public double calculateOrderDiscount(double price) {
        if (price > 1000) {
            return price * 0.9;
        }
        return price;
    }
}

public class CartService {

    public double calculateCartDiscount(double price) {
        if (price > 1000) {
            return price * 0.9;
        }
        return price;
    }
}

What’s wrong here?

  • Same logic duplicated

  • If discount rule changes → update in multiple places

  • High risk of inconsistency

This is a classic DRY violation.


Applying DRY (Good Code)

We extract the common logic into a single reusable component.

public class DiscountUtil {

    public static double applyDiscount(double price) {
        if (price > 1000) {
            return price * 0.9;
        }
        return price;
    }
}

Refactored Usage

public class OrderService {

    public double calculateOrderDiscount(double price) {
        return DiscountUtil.applyDiscount(price);
    }
}

public class CartService {

    public double calculateCartDiscount(double price) {
        return DiscountUtil.applyDiscount(price);
    }
}

Result:

✔ Single source of truth
✔ Easy to modify
✔ Clean and reusable


DRY Flow (How Refactoring Works)

Before DRY

OrderService → Discount Logic
CartService  → Discount Logic

After DRY

OrderService ─┐
              ├─> DiscountUtil
CartService ──┘

One logic → multiple consumers.


Real-World Analogy 🏭

Imagine a factory:

Without DRY
Each department builds its own machine for the same task.

With DRY
One central machine, reused by all departments.

In software:

  • Machine = reusable method/class

  • Departments = services/modules


DRY in Common Java Scenarios

Area

DRY Application

Validation

Central validation utility

Logging

Common logger wrapper

Constants

final static constants class

DB Queries

Repository / DAO layer

Business Rules

Service or domain layer


DRY vs Over-Abstraction ⚠️

DRY does not mean:

  • Creating unnecessary helper classes

  • Abstracting logic used only once

💡 Rule of thumb

Apply DRY when duplication represents shared knowledge, not accidental similarity.


Key Takeaways

  • DRY reduces bugs and improves maintainability

  • Refactor duplicate logic into reusable components

  • Use utility classes, services, and constants wisely

  • Avoid over-engineering


Design Principles for Java Developers

Part 9 of 10

This series explains core Java design principles and SOLID principles with simple examples, real-world use cases, and interview-focused explanations to help developers write clean, maintainable, and scalable code.

Up next

Introduction: Design Principles in Java

As software developers, we often focus on making things work. But as systems grow, teams expand, and requirements change, a more important question arises: Can this code survive change? This is where design principles come into play. Design princip...