Post
JA EN

If AI Is Increasing Duplication, DRY Should Be Enforced More Strictly: A Rebuttal to "The Wrong Abstraction"

If AI Is Increasing Duplication, DRY Should Be Enforced More Strictly: A Rebuttal to "The Wrong Abstraction"
  • Target audience: Software engineers, tech leads, and developers who use AI coding tools daily
  • Prerequisites: Basic familiarity with DRY and code clones, hands-on experience with AI coding agents (Claude Code, Cursor, etc.)
  • Reading time: 15 minutes

Overview

“Prefer duplication over the wrong abstraction.” Sandi Metz’s line has become something close to received wisdom in software design over the past decade. Now that AI coding agents write code every day, it sounds even more convenient than before. Duplicate it now, let AI clean it up in bulk later. Isn’t that safer than forcing a shared abstraction that turns out wrong?

The line has always had a rebuttal, though. Engineer Jason Swett argues that Metz’s claim oversimplifies the problem. “Wrong abstraction,” in his view, is a euphemism for what’s really just bad code, and the actually dangerous thing is duplication itself. Duplicated code sitting undetected across a codebase creates a silent inconsistency: fix one instance, forget the other, and nobody notices until it matters. This isn’t a theoretical worry. A landmark 2009 ICSE study found that 52% of code clones had been changed inconsistently, and 15% of those inconsistencies had introduced real faults1.

That disagreement takes on new weight in the age of AI coding. AI tends to duplicate code precisely because it doesn’t see implementations outside its current context. That exact blind spot is the worst-case scenario Swett describes: undetected duplication. Expecting the same AI, later, to notice that duplication and clean it up in bulk is a fairly optimistic bet, given that not noticing is the reason the duplication existed in the first place.

There’s another layer to AI-generated code specifically. Veracode’s 2025 analysis found that 45% of code produced by over 100 LLMs failed security testing and introduced OWASP Top 10 vulnerabilities2. Code quality platform Qodo.ai reports that more than 70% of security issues trace back to duplicated or inconsistent implementations, not brand-new vulnerabilities3. If the same flawed pattern gets silently copied across multiple places, or multiple repositories, “we’ll catch it eventually” isn’t good enough.

This piece revisits the classic rebuttal to Metz using AI-era data, and lands on the opposite practical conclusion from its companion piece: don’t tolerate duplication and hope AI cleans it up, catch it strictly at review time. That stance has real limits too, and this piece is upfront about them.

How “Fear the Wrong Abstraction More Than Duplication” Became Consensus

Sandi Metz’s RailsConf 2014 line, “prefer duplication over the wrong abstraction,” got cited widely enough afterward to feed into Kent C. Dodds’s middle path, AHA (Avoid Hasty Abstractions). Don’t fear duplication; wait until the same code is running in several places before letting the commonality argue its own case for an abstraction.

The reasoning traces back to a specific pattern Metz observed. A programmer spots duplication and extracts it into a function. A requirement shows up later that’s almost, but not quite, what the abstraction handles, and the next person, feeling obligated to preserve it, bolts on a parameter and a conditional. Repeat that a few times and a once-simple abstraction turns into an unreadable tangle of branches. That observation holds up; anyone who’s worked in a large codebase has seen it happen.

The problem is the leap from that observation to “so duplication is the safer choice.”

Swett’s Rebuttal: “Wrong Abstraction” Is Just a Euphemism

Jason Swett pushes back on Metz directly. First, question the term “wrong abstraction” itself. Code that’s collapsed into an unreadable pile of conditionals never deserved to be called an abstraction in the first place. It’s just poorly written code, and that’s not a defect in the concept of abstraction. The terminology, in his view, obscures the actual problem rather than clarifying it.

Second, and more central to Swett’s argument, is duplication’s hidden cost. The worst-case scenario for duplication is that it sits undetected somewhere in the codebase. One instance gets changed, the other doesn’t, and the resulting inconsistency causes trouble in production without anyone noticing. Swett calls this “one of the most dangerous mistakes in coding.” A pile of conditionals, at least, is visible; someone eventually looks at it and says “this is a mess” and refactors it. Silent, scattered duplication stays invisible until someone stumbles onto it.

Swett goes further and traces the reluctance to refactor existing code back to a deeper organizational problem: weak test coverage, a lack of collective code ownership, a culture driven by fear of breaking things. The fix, in his framing, isn’t tolerating duplication, it’s addressing those root causes through automated testing, continuous deployment, and a collaborative review culture.

AI Coding Adds New Weight to This Disagreement

Up to this point, this has been a decade-old argument about code humans write. Once AI agents are writing code daily, the dynamics of that argument shift.

The reason is straightforward. AI tends to produce duplicate code because it often generates without knowing about implementations sitting outside the files or directories it’s currently reading. 65% of developers say AI tools frequently miss relevant context during refactoring or review3. AI-generated code in particular tends to regenerate existing logic without knowing a shared library already covers it.

This is exactly the worst-case scenario Swett describes. AI is structurally more prone than a human to producing “undetected duplication.” And the broader trend backs this up: the share of copy-pasted lines and duplicated code blocks has been rising since AI adoption spread, and AI-generated pull requests reuse less code and duplicate more than human-written ones according to independent research45.

Here’s where it gets interesting. “Duplicate it now, have AI fix it in bulk later” carries a hidden assumption: someone, or something, has to first notice that the duplication represents the same knowledge. That noticing is exactly what AI struggles with. Expecting an AI that produces duplication because it can’t see outside its context to later notice that same duplication and consolidate it is betting twice on the same weakness. Code that got duplicated because it wasn’t visible isn’t obviously going to get found by an AI that still can’t see it.

To be fair, in a sufficiently visible environment, a well-organized monorepo, or an agent given enough context, this concern eases somewhat. But building that visibility and tolerating invisible duplication while hoping someone eventually notices are two very different things. One is a design investment. The other is deferral.

In Security Contexts, the Cost of Deferral Goes Up Sharply

This deferral stops being an abstract argument once the code in question touches security or compliance.

Veracode’s 2025 report tested over 100 large language models across Java, Python, C#, and JavaScript, 80 coding tasks total, and found that 45% of generated code failed security testing and introduced OWASP Top 10 vulnerabilities2. Model size and recency showed no correlation with security performance. The ability to write syntactically correct code improved; the ability to write secure code stayed flat regardless of model scale.

Qodo.ai’s analysis approaches the same problem from the duplication angle. More than 70% of security issues, according to their reporting, trace back not to brand-new vulnerabilities but to duplicated or inconsistent implementations3. Service-to-service integration logic, auth headers, retry loops, timeout handling, shows up repeatedly as the kind of code prone to this.

Put those two together and a shape emerges. AI generates flawed patterns at some measurable rate. AI also copies those patterns, without noticing, into places outside its current context. The result is the same vulnerability quietly spreading across multiple locations, possibly multiple services or repositories, rather than staying contained to one. Auditing repos one at a time won’t catch that lateral spread.

Given that, “AI will eventually notice and fix it in bulk” looks like a risky bet. The window during which the flawed pattern runs in production, multiple times, before anyone catches it, can easily outlast the window before it gets fixed. Dodds’s patience, wait until the same code shows up in several places before the commonality argues for an abstraction, simply doesn’t fit domains like authentication or payments. By the time the commonality is loud enough to notice, the duplicate has already executed in production more times than anyone would like.

Which Is Why Detection Belongs at Review Time, Strictly

Given all this, the practical conclusion runs opposite to AHA’s wait-and-see stance. When AI proposes code that duplicates existing logic, the answer shouldn’t be “it’s not time to abstract this yet.” It should be a default block at review time.

This isn’t just a principle, it’s something teams can start building toward now. Duplication can be classified as exact, near (different variable names or branch order, same logic), or semantic (different code, same behavior), and tooling that tries to catch behaviorally-identical code regardless of appearance is starting to emerge (semantic duplicate detection at high precision is still an evolving area, not a solved problem). Even so, treating this kind of detection as a mechanical gate at the pull request stage means catching duplication AI didn’t notice before a human has to notice it after the fact.

In Swett’s framing, this is also a safeguard against swapping one form of deferral for another. Relying on AI to consolidate duplication later carries the same structural risk as “we’ll write tests later” or “we’ll refactor later.” Organizations without solid test coverage or a collaborative review culture tend not to actually do the deferred work; it just piles up.

This Position Has Limits Too

It wouldn’t be honest to generalize this into “always enforce strict DRY, no exceptions.”

First, the claim that code clones reliably cause bugs isn’t settled in the literature. The 2009 study cited above found 52% of clones changed inconsistently and 15% of those causing faults. A contemporaneous study looked at the same question at release level and found that only 1.02% to 4.00% of clone lineages actually introduced defects by release time6. The granularity of analysis, per-commit versus per-release, changes how much real harm duplication appears to cause. Plenty of inconsistencies get absorbed by someone before they ever cause a problem.

Second, zero-tolerance duplication policies carry their own cost. Mechanically blocking every similar-looking code snippet increases review friction, and risks forcing genuinely different pieces of knowledge (code that happens to look alike after correctly avoiding Metz’s wrong abstraction) into one artificial abstraction. That’s the wrong abstraction Metz warned about, ironically triggered by the detection tooling itself.

So this argument mostly applies to domains where a mismatched interpretation causes real incidents: authentication, billing, permission checks, external integrations, or anything subject to regulatory or audit requirements. Experimental features and areas where requirements haven’t settled don’t need the same rigor.

Conclusion

“Duplicate it now, let AI fix it in bulk later” carries a hidden assumption: someone has to notice the duplication first. But the very reason AI produces duplication, not seeing implementations outside its context, is the same reason it struggles to notice and consolidate that duplication afterward. Jason Swett’s rebuttal to Sandi Metz, that undetected duplication is the actual worst-case scenario, maps onto that structure almost exactly. In domains like authentication and security, where a mismatched interpretation causes real incidents, deferring that cleanup isn’t a small cost.

Which is why, at least in some domains, catching duplication mechanically at review time makes more sense than AHA’s wait-and-see. That said, it’s not a universal answer. The academic evidence is genuinely split, and detection that’s too aggressive creates its own friction. In the end, how much duplication to tolerate from AI comes down to how much a mistake in that particular piece of knowledge would cost you.

The other side of this argument: This piece built its case around a rebuttal to Sandi Metz. The companion piece AI Is Increasing Code Duplication While Changing What Sharing Means uses the same AI-era data to reach the opposite practical conclusion: tolerate some duplication and let AI consolidate it in bulk later. Which stance fits your team depends on what the duplicated knowledge actually is, and what a mistake there would cost. Worth reading both before deciding.

You might also find these articles relevant:

References

Numbered citations in the text correspond to the sources below, listed in order.

Additional sources (referenced but not numbered in text)

  1. Do Code Clones Matter? - Elmar Juergens, Florian Deissenboeck, Benjamin Hummel, Stefan Wagner, ICSE 2009 (reposted to arXiv in 2017). 【Reliability: High】 ↩︎

  2. 2025 GenAI Code Security Report - Veracode (2025). 【Reliability: Medium-High】 ↩︎ ↩︎2

  3. How to Catch Code Duplication Across 100 Repositories - Nnenna Ndukwe, Qodo.ai (2026). 【Reliability: Medium】 ↩︎ ↩︎2 ↩︎3

  4. AI Copilot Code Quality: 2025 Data Suggests 4x Growth in Code Clones - GitClear (2025). 【Reliability: Medium-High】 ↩︎

  5. More Code, Less Reuse: Investigating Code Quality and Reviewer Sentiment towards AI-generated Pull Requests - MSR ‘26 conference paper (2026). 【Reliability: Medium-High】 ↩︎

  6. An Empirical Study on Inconsistent Changes to Code Clones at Release Level - Bettenburg et al., WCRE 2009. 【Reliability: Medium-High】 ↩︎

This post is licensed under CC BY 4.0 by the author.