dry-and-reuse — search before you build, consolidate before you clone
Purpose: kill the duplication that gives AI code its short shelf life. GitClear's
211M-line study found copy-pasted code now exceeds refactored code for the first time
ever, and duplicated blocks rose 8× — because agents reflexively add and almost never
move/merge. Duplicated blocks carry 15–50% more defects. The senior move is to find
what exists and reuse it.
DRY is about knowledge, not text
The real rule (Pragmatic Programmer): every piece of knowledge has a single,
authoritative representation. Two consequences agents get wrong in both directions:
- Two blocks that look alike but encode different decisions are not a DRY
violation — don't force them into one abstraction (that's coupling unrelated things).
- One business rule expressed in three places is a violation even if the code looks
different each time — that's the dangerous kind, because the copies drift.
Reflex card
- Search before you build. Before writing a helper/util/type/constant, grep the
codebase (and the stdlib, and existing deps) for one that already does it. Reuse beats
rewrite, every time.
- Consolidate, don't clone. About to copy-paste a block? Extract it to one place and
call it twice instead. Copy-paste is a debt you pay at every future change.
- Move/merge, don't only add. The healthiest diffs delete and relocate code as
well as adding it. If your change is pure addition and you suspect overlap, look
harder. The refactored-to-duplicated ratio is the #1 quality signal.
- One rule, one home. A validation rule, a tax calculation, a status enum, a magic
constant — define it once and import it. Never let the same knowledge live in two
files.
- Reuse the stdlib first. Don't hand-roll what
itertools/lodash/slices/Intl
already gives you. Reinventing stdlib is DRY slop and a bug farm.
- But don't abstract incidental similarity. If pulling two look-alikes together
requires flags and special-cases to keep them apart, they were different rules —
leave them. (Hand the judgment to
craft:right-sized-design.)
Red flags
- A new function whose body you've seen elsewhere in the repo.
- The same constant / regex / URL / status string in 2+ files.
- A block copy-pasted and then lightly edited (the most defect-prone pattern).
- The same business rule (discount, tax, permission check) computed in several places.
- A util that re-implements
groupBy, debounce, chunk, deepEqual, date math, etc.
- A "v2" of a function sitting next to "v1" with 90% overlap.
- A diff that only ever adds, never moves or deletes, across a large change.
The procedure
- Before writing: search by intent (what it does), not just by name — agents miss
existing helpers because they searched for the wrong noun. Grep for the operation, the
constant's value, the rule's keywords.
- On a hit: reuse it. If it's almost right, extend the existing one (carefully,
without breaking its other callers) rather than forking a copy.
- On real duplication found in review: extract to a single home (hand the mechanics
to
refactoring-patterns: Extract Function, Pull Up Method, Extract Class). Place the
single source where both callers can reach it without creating a bad dependency.
- Confirm it's knowledge duplication, not coincidence, before merging — see the
"incidental similarity" caveat above.
Inline example
# ❌ Agent clones the rule into a third place
def can_edit(user, doc):
return user.role == "admin" or user.id == doc.owner_id # rule copy #3
# ✅ One authoritative home, reused
# permissions.py
def can_edit(user, doc) -> bool:
"""Single source of truth for edit permission."""
return user.is_admin or user.id == doc.owner_id
# everywhere else: from permissions import can_edit
When the rule changes (say, editors can also edit), you change it once — not hunt three
drifted copies.
Critique mode
Scan the diff for repeated logic, duplicated constants, and reinvented stdlib/existing
utilities. For each: is this knowledge duplication (consolidate) or incidental
similarity (leave it)? Tag [dry-and-reuse · duplicate-knowledge|reinvented-util · SEV].
Cross-check suspected structural duplication with dependency-analyzer.
References
- DRY-as-knowledge:
../../references/PRINCIPLES.md §A
- Duplicate Code / Repetition:
../../references/SMELLS.md
- The GitClear data:
../../references/EVIDENCE.md
- Rules 3 & 4:
../../RULES.md
1---2name: dry-and-reuse3description: Stops duplication and reinvention — the failure GitClear measures as "rework" (copy-paste up, refactoring down, the signature of AI code with a short shelf life). Use before writing any helper, util, type, constant, or component, and when reviewing a diff for repeated logic. Enforces search-before-build, consolidate- don't-clone, and DRY-as-knowledge (one rule, one authoritative place). Triggers: "is there already a function for this", "this looks duplicated", "DRY this up", "extract the common logic", "we keep rewriting this", before adding any utility.4---56# dry-and-reuse — search before you build, consolidate before you clone78**Purpose**: kill the duplication that gives AI code its short shelf life. GitClear's9211M-line study found copy-pasted code now *exceeds* refactored code for the first time10ever, and duplicated blocks rose 8× — because agents reflexively *add* and almost never11*move/merge*. Duplicated blocks carry 15–50% more defects. The senior move is to find12what exists and reuse it.1314## DRY is about knowledge, not text1516The real rule (Pragmatic Programmer): **every piece of *knowledge* has a single,17authoritative representation.** Two consequences agents get wrong in both directions:18- Two blocks that *look* alike but encode **different decisions** are **not** a DRY19 violation — don't force them into one abstraction (that's coupling unrelated things).20- One business rule expressed in three places **is** a violation even if the code looks21 different each time — that's the dangerous kind, because the copies drift.2223## Reflex card24251. **Search before you build.** Before writing a helper/util/type/constant, grep the26 codebase (and the stdlib, and existing deps) for one that already does it. Reuse beats27 rewrite, every time.282. **Consolidate, don't clone.** About to copy-paste a block? Extract it to one place and29 call it twice instead. Copy-paste is a debt you pay at every future change.303. **Move/merge, don't only add.** The healthiest diffs *delete* and *relocate* code as31 well as adding it. If your change is pure addition and you suspect overlap, look32 harder. The refactored-to-duplicated ratio is the #1 quality signal.334. **One rule, one home.** A validation rule, a tax calculation, a status enum, a magic34 constant — define it once and import it. Never let the same knowledge live in two35 files.365. **Reuse the stdlib first.** Don't hand-roll what `itertools`/`lodash`/`slices`/`Intl`37 already gives you. Reinventing stdlib is DRY slop *and* a bug farm.386. **But don't abstract incidental similarity.** If pulling two look-alikes together39 requires flags and special-cases to keep them apart, they were different rules —40 leave them. (Hand the judgment to `craft:right-sized-design`.)4142## Red flags4344- A new function whose body you've seen elsewhere in the repo.45- The same constant / regex / URL / status string in 2+ files.46- A block copy-pasted and then lightly edited (the most defect-prone pattern).47- The same business rule (discount, tax, permission check) computed in several places.48- A util that re-implements `groupBy`, `debounce`, `chunk`, `deepEqual`, date math, etc.49- A "v2" of a function sitting next to "v1" with 90% overlap.50- A diff that only ever adds, never moves or deletes, across a large change.5152## The procedure53541. **Before writing:** search by intent (what it *does*), not just by name — agents miss55 existing helpers because they searched for the wrong noun. Grep for the operation, the56 constant's value, the rule's keywords.572. **On a hit:** reuse it. If it's *almost* right, extend the existing one (carefully,58 without breaking its other callers) rather than forking a copy.593. **On real duplication found in review:** extract to a single home (hand the mechanics60 to `refactoring-patterns`: Extract Function, Pull Up Method, Extract Class). Place the61 single source where both callers can reach it without creating a bad dependency.624. **Confirm it's *knowledge* duplication, not coincidence,** before merging — see the63 "incidental similarity" caveat above.6465## Inline example6667```python68# ❌ Agent clones the rule into a third place69def can_edit(user, doc):70 return user.role == "admin" or user.id == doc.owner_id # rule copy #37172# ✅ One authoritative home, reused73# permissions.py74def can_edit(user, doc) -> bool:75 """Single source of truth for edit permission."""76 return user.is_admin or user.id == doc.owner_id77# everywhere else: from permissions import can_edit78```79When the rule changes (say, editors can also edit), you change it once — not hunt three80drifted copies.8182## Critique mode8384Scan the diff for repeated logic, duplicated constants, and reinvented stdlib/existing85utilities. For each: is this *knowledge* duplication (consolidate) or incidental86similarity (leave it)? Tag `[dry-and-reuse · duplicate-knowledge|reinvented-util · SEV]`.87Cross-check suspected structural duplication with `dependency-analyzer`.8889## References90- DRY-as-knowledge: `../../references/PRINCIPLES.md` §A91- Duplicate Code / Repetition: `../../references/SMELLS.md`92- The GitClear data: `../../references/EVIDENCE.md`93- Rules 3 & 4: `../../RULES.md`