What is DRY
DRY stands for Don't Repeat Yourself. Every piece of knowledge should have a single, unambiguous representation within a system.
The Principle
DRY: Don't Repeat Yourself
Every piece of knowledge must have a single, authoritative
representation within a system.
— Andy Hunt & Dave Thomas, The Pragmatic Programmer
Types of Duplication
| Type | Description | Example |
|---|---|---|
| Code duplication | Same code in multiple places | Copy-pasted functions |
| Logic duplication | Same logic, different code | Two ways to validate email |
| Knowledge duplication | Same fact defined in multiple places | Config in 3 files |
| Temporal duplication | Same action at multiple times | Same init in 5 places |
Why DRY Matters
- Change one place → forget another → bugs
- Multiple sources of truth → confusion
- Harder to maintain → technical debt
With DRY:
- Change one place → all instances updated
- Single source of truth → clarity
- Easier to maintain → clean code
The Cost of Duplication
1 copy of code → No problem
2 copies of code → Acceptable if truly independent
3 copies of code → DRY violation, refactor!
"Duplication is far more expensive than it appears"
— Andy Hunt & Dave Thomas
Common Violations
Recognizing DRY violations is the first step to eliminating them.
Violation 1: Copy-Paste Code
// BAD: Same validation logic in multiple places
public class UserService {
public void createUser(String email) {
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
// ... create user
}
}
public class NewsletterService {
public void subscribe(String email) {
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
// ... subscribe
}
}
Violation 2: Magic Numbers
// BAD: Hardcoded values everywhere
if (items.size() > 100) { ... }
if (name.length() > 50) { ... }
Thread.sleep(3000);
// GOOD: Named constants
public static final int MAX_CART_ITEMS = 100;
public static final int MAX_NAME_LENGTH = 50;
public static final int RETRY_DELAY_MS = 3000;
Violation 3: Duplicated Logic
// BAD: Two methods doing the same thing differently
public double calculateArea(double radius) {
return 3.14159 * radius * radius;
}
public double computeArea(double r) {
return 3.14159 * r * r;
}
// GOOD: Single method
public double calculateCircleArea(double radius) {
return Math.PI * radius * radius;
}
Violation 4: Repeated Configuration
// BAD: Same config in multiple files
// file1.properties
url=jdbc:mysql://localhost:3306/mydb
// file2.properties
url=jdbc:mysql://localhost:3306/mydb
// file3.properties
url=jdbc:mysql://localhost:3306/mydb
// GOOD: Single config source
// config.properties
url=jdbc:mysql://localhost:3306/mydb
// All other files reference this
Violation 5: Similar Classes
// BAD: Two classes doing nearly the same thing
class EmailNotification {
public void send(String to, String message) {
// email logic
}
}
class SMSNotification {
public void send(String to, String message) {
// sms logic (very similar)
}
}
// GOOD: Abstraction
interface Notification {
void send(String to, String message);
}
When Duplication is OK
- When changes are independent
- When abstractions would be premature
- When copies serve different purposes
- When the cost of DRY exceeds the benefit
How to Apply
Applying DRY effectively requires identifying the right abstraction level.
DRY Techniques
1. Extract Method
// Before
void processOrder() {
// 20 lines of validation
// 10 lines of calculation
// 15 lines of persistence
}
// After
void processOrder() {
validateOrder();
calculateTotal();
saveOrder();
}
2. Extract Class
// Before: UserService does everything
class UserService {
void createUser() { ... }
void validateEmail() { ... }
void sendWelcomeEmail() { ... }
void logActivity() { ... }
}
// After: Separate classes
class UserService { void createUser() { ... } }
class EmailValidator { void validateEmail() { ... } }
class WelcomeEmailSender { void sendWelcome() { ... } }
class ActivityLogger { void logActivity() { ... } }
3. Template Method
// Before: Similar algorithms in multiple classes
class PDFReport {
void generate() {
openDocument();
addHeader();
addContent();
addFooter();
closeDocument();
}
}
class HTMLReport {
void generate() {
openDocument();
addHeader();
addContent();
addFooter();
closeDocument();
}
}
// After: Template method
abstract class Report {
final void generate() {
openDocument();
addHeader();
addContent();
addFooter();
closeDocument();
}
protected abstract void addContent();
}
4. Composition
// Before: Repeated formatting logic
class UserFormatter {
String format(User u) {
return u.getName().toUpperCase() + ", " + u.getEmail();
}
}
class AdminFormatter {
String format(Admin a) {
return a.getName().toUpperCase() + ", " + a.getEmail();
}
}
// After: Shared formatter
class NameEmailFormatter {
String format(String name, String email) {
return name.toUpperCase() + ", " + email;
}
}
DRY Checklist
- Is the same logic in 3+ places? → Extract
- Is the same fact defined in 3+ places? → Single source
- Is the same string/number repeated? → Constant
- Are two classes very similar? → Inheritance or composition
- Is there a pattern? → Template or Strategy
DRY Anti-Patterns
| Anti-Pattern | Problem |
|---|---|
| Premature DRY | Abstracting too early |
| Over-engineering | Making everything generic |
| Copy-paste | Not DRY at all |
| DRY for DRY's sake | When duplication is OK |
Balance DRY with YAGNI
Don't abstract until you see at least 3 instances of duplication. Premature abstraction can be worse than duplication.
Practice Problems
Design a scalable DRY system. Cover high-level architecture, data model, and API design.
Solution
// Complete system design:
// - Functional + Non-functional requirements
// - Capacity estimation
// - Data model (SQL/NoSQL choice)
// - API endpoints
// - Component architecture
// - Scaling strategy
// - Monitoring & reliabilityHow would you scale DRY to handle 10x the current load? Identify bottlenecks and solutions.
Solution
// Scaling approach:
// 1. Load balancing
// 2. Database sharding/replication
// 3. Cache layer (Redis)
// 4. CDN for static assets
// 5. Async processing (queues)
// 6. Microservices decompositionAnalyze potential failure modes for DRY and design mitigation strategies.
Solution
// Failure mitigation:
// 1. Redundancy (multi-AZ)
// 2. Circuit breakers
// 3. Retry with backoff
// 4. Dead letter queues
// 5. Health checks
// 6. Graceful degradationQuiz
1. What does DRY stand for?
2. When is duplication acceptable?
3. What technique eliminates repeated magic numbers?
4. At how many instances of duplication should you consider DRY?
5. What is a DRY violation?
Flashcards
Question
What is DRY?
Click to reveal answer
Answer
Don't Repeat Yourself. Every piece of knowledge should have a single, authoritative representation. Reduces bugs and maintenance cost.
Question
What are 4 types of duplication?
Click to reveal answer
Answer
Code duplication (same code), Logic duplication (same logic, different code), Knowledge duplication (same fact in multiple places), Temporal duplication (same action at multiple times).
Question
How to apply DRY?
Click to reveal answer
Answer
Extract Method, Extract Class, Template Method, Composition, Named Constants, Single Source of Truth.
Question
When is duplication acceptable?
Click to reveal answer
Answer
When changes are independent, when premature abstraction adds more complexity, or when copies serve genuinely different purposes.
Question
What is the DRY anti-pattern?
Click to reveal answer
Answer
Premature DRY: abstracting too early before the pattern is clear. Can be worse than keeping duplication.
Revision Notes
Key Takeaways
- 1.DRY means every piece of knowledge has a single authoritative representation
- 2.Common violations: copy-paste code, magic numbers, duplicated logic, similar classes
- 3.Apply DRY when you see 3+ instances of the same pattern
- 4.Balance DRY with YAGNI — don't abstract prematurely
- 5.DRY reduces bugs, simplifies maintenance, and improves clarity
Interview Tips
- •Mention DRY when discussing code quality and maintainability
- •Show how you'd extract common logic to eliminate duplication
- •Explain the balance between DRY and YAGNI in design decisions
- •Discuss when duplication is acceptable vs when to abstract
Cheat Sheet
DRY - Cheat Sheet
Definition:
Don't Repeat Yourself. Single source of truth.
Types of Duplication:
- Code (copy-paste)
- Logic (same logic, different code)
- Knowledge (same fact, multiple places)
- Temporal (same action, multiple times)
Techniques:
- Extract Method
- Extract Class
- Template Method
- Composition
- Named Constants
Apply When:
- 3+ instances of same logic
- Same fact in 3+ places
- Same string/number repeated
- Two very similar classes
Don't Apply When:
- Only 2 instances
- Changes are independent
- Abstraction adds complexity