Want to learn more about Faros AI?

Fill out this form to speak to a product expert.

I'm interested in...
Loading calendar...
An illustration of a lighthouse in the sea

Thank you!

A Faros AI expert will reach out to schedule a time to talk.
P.S. If you don't see it within one business day, please check your spam folder.
Oops! Something went wrong while submitting the form.
Submitting...
An illustration of a lighthouse in the sea

Thank you!

A Faros AI expert will reach out to schedule a time to talk.
P.S. If you don't see it within one business day, please check your spam folder.
Oops! Something went wrong while submitting the form.

DRY Principle in Programming: Preventing Duplication in AI-Generated Code

Understand the DRY principle in programming, why it matters for safe, reliable AI-assisted development, and how to prevent AI agents from generating duplicate or inconsistent code.

Neely Dunlap
Neely Dunlap
Graphic with a blue code-themed background showing the text ‘the DRY principle & AI generated code’ framed by stylized angle brackets.
10
min read
Browse Chapters
Share
November 26, 2025

From maintainability to AI readiness: The DRY principle’s enduring importance

In software development, some ideas are so powerful that they ripple across languages, frameworks, architectures, and even entire engineering cultures. The DRY principle is one of those ideas. Standing for “Don’t Repeat Yourself,” it’s a deceptively simple rule with profound implications for how we design, maintain, and scale software systems.

But the DRY principle is also among the most misunderstood concepts in programming. Many developers mistakenly reduce it to “don’t copy-paste code,” while others misuse it to create overly generic, painfully abstract systems. In reality, DRY is about something deeper: ensuring that every piece of knowledge in your system has a single, authoritative source of truth.

In this guide, we’ll explore:

  • How the DRY principle emerged from The Pragmatic Programmer
  • DRY’s conceptual foundations and benefits 
  • How to apply DRY realistically across codebases and architectures
  • Why DRY is essential for safe, reliable AI-assisted development
  • How to prevent AI agents from violating the DRY principle

By the end, you’ll understand not only what DRY is, but when to apply it, how to avoid over-abstracting, and how to use it as a tool (not a dogma) for creating maintainable, scalable systems.

{{cta}}

Where did the DRY principle come from?

The DRY principle was introduced by Andy Hunt and Dave Thomas in their landmark 1999 book The Pragmatic Programmer, a book that has shaped how multiple generations of engineers think about software design.

One of the most memorable stories in the book involves a large financial system used by multiple departments: accounting, compliance, and auditing. Each department needed to produce nearly identical reports using the same financial rules.

Except… they didn’t use the same rules.

Each team had created its own implementation of the business logic—not because they wanted to, but because repeated logic had quietly crept into the codebase over years of incremental development. As a result:

  • A tax regulation update would be implemented in one report but not another
  • Rounding rules differed subtly between departments
  • Interest calculations produced conflicting results
  • Bugs multiplied because “the truth” existed in multiple inconsistent versions

The authors describe the chaos that unfolded: nobody trusted the system, every team blamed the others, and developers spent weeks tracking down inconsistencies caused not by complex mathematics, but by duplicated knowledge.

The solution was transformative.

The team consolidated the business logic into a single reporting engine. Instead of three systems with three interpretations of the rules, there was now one implementation consumed by all departments.

The result?

  • A bug fix applied everywhere instantly
  • Reports became consistent
  • Maintenance time dropped
  • The system became stable for the first time

This experience crystallized a core insight:

“Duplication is the root of all evil in software.”
—Hunt & Thomas, The Pragmatic Programmer

And from that insight, the DRY principle was born:

Every piece of knowledge must have a single, unambiguous, authoritative representation in a system.

This idea, simple yet profound, became the foundation of modern DRY principle programming.

What is the DRY principle in software development?

The DRY principle (“Don’t Repeat Yourself”) means that you should avoid writing the same logic in multiple places. Instead, you keep each piece of knowledge or functionality in one clear, central spot so it’s easy to update, reuse, and maintain without creating inconsistencies or extra work.

Violations of the DRY principle

Since the premise of DRY seems simple, let’s look at what violating it looks like. Many developers incorrectly interpret DRY as: “Don’t duplicate code.” But the DRY principle in programming isn’t about code. It’s about meaning, knowledge, and intent. 

You’re violating DRY when you duplicate:

  • Business rules (e.g., “users must be 18 or older”)
  • Validation logic
  • API contract definitions
  • Data transformation rules
  • Configuration values
  • Database schemas
  • Domain concepts

These forms of duplication may not look like copy-paste code. They might exist as separate functions, modules, or services that encode the same concept in different ways. This type of duplication is dangerous, because it creates drift and inconsistency across your systems. Examples include:

  • The web app enforces a minimum password length of 8 characters, the mobile app enforces 10, and the backend enforces 6.
  • Your front-end TypeScript types diverge from your OpenAPI schema because they were manually maintained.
  • Business rules for promotions are reimplemented in two microservices.
  • Database column names exist in both SQL strings and ORM models.

In summary: You can violate DRY without copy-paste existing anywhere.

What are common misconceptions about the DRY principle in programming?

  1. DRY is not “abstract everything.”
    Just because two functions look similar doesn’t mean they represent the same concept.
    Example:
    sendEmail() and sendSMS() might share some structure, but abstracting them prematurely into a single function may actually increase complexity.
  2. DRY is not “never duplicate anything.”
    Some duplication is harmless or even beneficial—especially in tests (more on this later).
  3. DRY is not a goal in itself.
    DRY is a tool for reducing inconsistency, not a stylistic rule to obey blindly.

The real cost of business logic duplication: Why it’s important to follow the DRY principle in programming

Duplication is cheap in the moment and expensive in the long run.

If you’ve ever had to fix a bug that was caused by overlooked duplicated logic, you know how painful it can be. The crippling cost of duplication shows up as:

  • Divergence — duplicated logic drifts apart over time.
  • Inconsistency — different parts of the system behave differently.
  • Unclear ownership — no one knows where the “real” rule lives.
  • Surprise side effects — fixing one place breaks another.
  • Complicated refactoring — changes require hunting down every copy.
  • Harder onboarding — new developers struggle to understand which version is correct.

Taken together, these costs erode the clarity and stability of the entire codebase. Consolidating business logic into a single, authoritative location is what allows a system to evolve predictably and sustainably.

What are the benefits of the DRY principle in programming?

When every rule and behavior has a single place to live, the whole system becomes easier to understand and work with. DRY strips away the noise, which in turn unlocks faster, safer iterations. A codebase organized around clear, singular sources of truth creates momentum with benefits that quickly compound:

DRY Benefits What It Means Why It Matters
Reduces Bugs Removes duplicated logic that inevitably drifts and becomes inconsistent. Eliminates system contradictions before they turn into user-facing bugs.
Improves Maintainability Concentrates logic in one authoritative location instead of scattering it across the codebase. Makes updates safe, fast, and predictable—no more hunting for hidden duplicates.
Reduces Cognitive Load Centralizes rules and data flows so developers don’t waste energy tracking multiple versions of the same logic. Frees developers’ mental bandwidth, speeding up comprehension and reducing mistakes.
Encourages Good Architecture Forces logic into cohesive modules and well-defined domains rather than ad-hoc duplication. Produces cleaner, scalable architecture with clearer ownership and reusable components.
Supports Scalability Establishes a single source of truth as teams, services, and codebases expand. Prevents systemic inconsistency and cuts communication overhead as organizations grow.
The benefits of the DRY principle in programming

What are the best practices in applying the DRY principle?

DRY is powerful—but dangerous in the hands of someone who applies it mechanically. The number one mistake developers make is applying DRY too early, creating brittle abstractions that make the system harder to understand. The right way to apply DRY is gradual and semantic, not premature and syntactic.

How to apply DRY correctly

1. Identify shared meaning, not shared syntax. Only abstract duplicated code when it represents the same concept.

Example: Two different discount calculation functions may look similar, but represent different rules. Don’t merge them unless they mean the same thing.

2. Use code generation. One schema → many outputs.

Tools like:

  • OpenAPI
  • GraphQL
  • Protobuf
  • Zod
  • JSON Schema

…allow you to generate:

  • Clients
  • Servers
  • Validators
  • Documentation
  • Types

This is the ultimate DRY solution for modern systems.

3. Refactor opportunistically. Don’t force abstractions too early. Instead, refactor when patterns emerge naturally.

Good DRY evolves—bad DRY is imposed.

4. Prefer declarative sources of truth. Declarative systems enforce DRY naturally.

Examples:

  • Terraform (infrastructure as code)
  • Kubernetes manifests
  • Database migration files
  • Schema-driven UI forms

Declarative = self-documenting = DRY.

5. Use well-scoped modules. Encapsulate logic inside modules that own their domain meaningfully.

But don’t force unrelated modules to share logic just because they have similar structures.

When NOT to use DRY (yes, really)

There are times when duplication is safer, cleaner, and more intentional.

1. When the abstraction reduces clarity → If combining two pieces of logic hides meaning, don’t do it.

2. When two concepts look similar but are actually different → This is the most common place where DRY is misused. Two features might share code now but diverge later. Binding them together creates future pain.

3. When the abstraction creates unnecessary coupling → Sharing a utility library across several microservices might violate boundaries and increase the blast radius of changes.

4. In tests → A readable test suite often contains repetition, and for good reason. Each test should tell a clear short story. Over-DRYed tests become unreadable.

A DRY rule of thumb: Duplication now is better than the wrong abstraction

This idea comes directly from the spirit of The Pragmatic Programmer.

When in doubt:

Wait.
Keep the duplication.
Only abstract once you fully understand the domain.

Good abstractions come from maturity.
Bad abstractions come from fear of duplication.

The growing strategic value of DRY in AI-driven development

Up to this point, we’ve been talking about DRY in the traditional, human sense—when to duplicate, when to wait, and when to abstract. But there’s a new layer now. AI is stepping into codebases, sometimes as a helper and sometimes as a decision-maker. And the moment machines start reading and modifying our code, the cost of duplication changes. Here’s how DRY plays out when AI becomes part of the team.

DRY and AI coding assistants

AI coding assistants, such as autocompletion tools, inline explainers, test generators, and refactor helpers, work best when the codebase tells a consistent story. These tools rely on patterns in your code to predict what you want next. When logic is centralized, an assistant can trace it, learn from it, and give suggestions that align with how your system actually behaves.

Duplication muddies that picture. If the same logic appears in multiple places (and one of those places is slightly outdated), the assistant has no way to know which one reflects the truth. This leads to odd completions, half-baked refactors, or suggestions that reinforce the wrong version of a pattern. And when you're moving quickly to accept suggestions or let the AI assistant fill in boilerplate code, those small inconsistencies compound over time.

DRY code gives AI coding tools a single, reliable reference point. It keeps the model’s understanding of your project clean and reduces the chance of misleading suggestions. You get sharper completions, smarter refactors, and fewer “why did it write that?” moments.

DRY and autonomous agents

Autonomous agents raise the stakes. These AI systems go beyond helping with isolated tasks, and are now scanning whole codebases, forming plans, making decisions, and applying changes across many files. When the same logic appears in several places—especially with small differences—an agent can treat each instance as a separate concept. It may update one copy and overlook the others, causing the logic to drift apart in ways that are hard for the agent to notice and even harder for humans to debug.

Autonomous agents navigate code through internal “maps”—semantic clusters, dependency graphs, retrieval traces—and duplication clutters those maps with mixed signals. A DRY codebase, by contrast, gives the agent one clear, authoritative place to understand a piece of logic, and that clarity helps it reason more accurately, update safely, and avoid cascading side effects. Thus, as machines begin reading and modifying our software alongside us, DRY stops being just a best practice, and instead becomes a way of keeping the code understandable to both humans and AI alike.

{{cta}}

How to help prevent AI agents from violating the DRY principle

Once you bring autonomous agents into your workflow, DRY isn’t just something you can violate. Agents can violate it, too. Unlike humans, agents don’t pause to ask whether a function or pattern already exists; they simply produce output based on the context available to them at that moment. Two common scenarios make duplication especially likely:

1. When the agent’s context is missing or poorly structured, it may generate new code rather than reusing what already exists.

Agents will generate a result regardless of whether the correct function, pattern, or abstraction already exists. If the context is incomplete (whether due to misconfigured MCP servers, missing or outdated agent.md files, or unclear retrieval instructions) the agent may:

  • Reinvent logic that’s already implemented
  • Apply a change in the wrong place
  • Create parallel versions of the same idea across multiple files

This isn’t to be attributed to a flaw in the model, as it’s merely a reflection of what the agent can “see.” When developers provide clear, well-organized context and point agents toward the correct sources of truth, the system naturally leans toward reuse rather than regeneration. Hence, thoughtful and thorough context design becomes a kind of DRY enforcement mechanism: give the agent the right map, and it’s much less likely to draw a new one.

2. When conversations exceed the model’s memory, the agent forgets and begins duplicating work.

Even with large context windows, agents have limits. Long sessions eventually push earlier messages out of memory, causing the agent to lose track of previous decisions. Once this happens, it may forget that certain abstractions or rules were already established and unintentionally create duplicates.

Model providers are working to mitigate this. Claude Code, for example, now compacts conversation history so earlier details are less likely to be lost as sessions grow. But until these solutions are consistently reliable across tools, developers can reduce duplication risk by following a few disciplined practices:

  • Create frequent checkpoints. Save and commit changes so progress does not rely on the agent remembering earlier steps.
  • Document new rules and patterns as they appear. This provides an external, stable reference the agent can retrieve.
  • Start fresh sessions when context becomes noisy. Then, reintroduce the latest guidance/truth so the agent can start fresh without being overwhelmed. 

These habits give agents stable reference points even as conversations reset or grow long, which reduces the risk of accidental duplication and keeps your codebase consistent over time.

Conclusion: The DRY principle as a philosophy of software design

The DRY principle in programming has survived decades because it captures a simple truth:
duplication is the enemy of consistency, clarity, and maintainability.

But remember: the DRY principle is not about code style; it’s about knowledge management.

To use DRY well:

  • Avoid duplicating meaning
  • Centralize rules & schemas
  • Use declarative definitions
  • Adopt code generation
  • Refactor gradually
  • Avoid premature abstraction
  • Keep tests explicit

The magic of DRY is in developing the skill to understand the meaning behind code and ensuring that meaning lives in one authoritative place. And in an era where AI reads, suggests, and even modifies our code, keeping that meaning coherent has never mattered more.

{{cta}}

Apply DRY with wisdom, and your systems will be cleaner, more resilient, and far easier to evolve.
Misapply it, and you’ll create brittle abstractions that hurt more than they help.

Like all powerful tools in software development, DRY works best when used pragmatically, exactly as Hunt and Thomas intended.

Neely Dunlap

Neely Dunlap

Neely Dunlap is a content strategist at Faros AI who writes about AI and software engineering.

Connect
AI Is Everywhere. Impact Isn’t.
75% of engineers use AI tools—yet most organizations see no measurable performance gains.

Read the report to uncover what’s holding teams back—and how to fix it fast.
Discover the Engineering Productivity Handbook
How to build a high-impact program that drives real results.

What to measure and why it matters.

And the 5 critical practices that turn data into impact.
Want to learn more about Faros AI?

Fill out this form and an expert will reach out to schedule time to talk.

Loading calendar...
An illustration of a lighthouse in the sea

Thank you!

A Faros AI expert will reach out to schedule a time to talk.
P.S. If you don't see it within one business day, please check your spam folder.
Oops! Something went wrong while submitting the form.

More articles for you

Editor's Pick
AI
DevProd
9
MIN READ

Are AI Coding Assistants Really Saving Time, Money and Effort?

Research from DORA, METR, Bain, GitHub and Faros AI shows AI coding assistant results vary wildly, from 26% faster to 19% slower. We break down what the industry data actually says about saving time, money, and effort, and why some organizations see ROI while others do not.
November 25, 2025
Editor's Pick
News
AI
DevProd
8
MIN READ

Faros AI Iwatani Release: Metrics to Measure Productivity Gains from AI Coding Tools

Get comprehensive metrics to measure productivity gains from AI coding tools. The Faros AI Iwatani Release helps engineering leaders determine which AI coding assistant offers the highest ROI through usage analytics, cost tracking, and productivity measurement frameworks.
October 31, 2025
Editor's Pick
AI
DevProd
9
MIN READ

Bain Technology Report 2025: Why AI Gains Are Stalling

The Bain Technology Report 2025 reveals why AI coding tools deliver only 10-15% productivity gains. Learn why companies aren't seeing ROI and how to fix it with lifecycle-wide transformation.
October 3, 2025