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 |
|
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




