VOOZH about

URL: https://dev.to/quotentiroler/dry-dont-repeat-yourself-24ag

⇱ DRY: Don't Repeat Yourself - DEV Community


When we wrote code before large language models could write it for us, code duplication was rarely our problem, at least not if we worked alone or in a small team.

That has changed.

A principle born in a quieter time

"Don't Repeat Yourself" was coined by Andy Hunt and Dave Thomas in The Pragmatic Programmer back in 1999, a year when our biggest worry was whether the clocks would survive January. The idea is reassuringly simple. Every piece of knowledge in your system should have a single, unambiguous home. Write it once, point at it from everywhere else, go to lunch.

For those of us working alone or in small teams, DRY was almost automatic. You held the whole codebase in your head, all of it, including the parts you were ashamed of. When you needed to format a date, you remembered you already had a formatDate helper, because you had written it last Tuesday and were still slightly proud of it. Duplication was something that happened to other people, specifically large organizations where three teams could write three subtly different currency formatters and never once meet in a corridor.

Duplication, in other words, was a problem that scaled with headcount. The more humans you added, the more copies of everything you got.

Now everyone gets to have the problem

Here is the shift. An LLM writing code for you behaves rather like a brand new contractor who has never seen your project, is enormously eager to help, and has politely forgotten everything the moment they finish each task.

It does not know that formatDate already exists. It does not know your team solemnly agreed that all network calls go through apiClient. It does not know that the precise validation logic it is about to invent is sitting, fully tested, three folders away. So it does the friendly thing and writes some fresh code that works.

And it does work. The tests pass, the feature ships, the little green checkmark appears, everyone is delighted. You simply now own a fourth date formatter, a second and mildly incompatible API wrapper, and a button component that matches your design system the way a cover band matches the original.

The duplication problem used to scale with the number of people. It now scales with the number of generations. A single developer with an AI assistant can produce, before lunch, the sort of sprawl that once required an entire floor of the building.

Why models duplicate without meaning to

It helps to understand why this happens, mostly because it points directly at the fix. There are really three reasons, and none of them involve the model being foolish.

The first is context. The model only sees what you hand it, and your 200-file project does not fit through the letterbox. It cannot reuse a helper it has never been allowed to look at. The second is incentive. Generating new code is the thing models are good at and rewarded for, whereas reusing old code first requires finding the old code, an activity most setups make about as convenient as it sounds. The third is more human than you would expect. A self-contained block that compiles simply feels finished, and nothing about "finished" nudges anyone, silicon or otherwise, to go hunting for the canonical version that already exists.

Notice that all three are about memory, not intelligence. The model is not failing to reason. It is reasoning brilliantly about the tiny slice of the world you managed to fit in front of it.

What it quietly costs you

Duplication is not merely untidy. It is where bugs go to retire comfortably.

// payments/checkout.ts
function formatPrice(cents: number) {
 return `$${(cents / 100).toFixed(2)}`;
}

// invoices/render.ts, written by an agent two weeks later
function priceToString(amount: number) {
 return `$${(amount / 100).toFixed(2)}`; // same idea, fresh coat of paint
}

These two look harmless, almost charming. Then you launch in Europe, need euros and comma decimals, and confidently patch formatPrice. The invoices keep cheerfully printing dollars, because nobody alive remembers that priceToString exists. You have just shipped a production bug whose root cause is a duplication that no human ever actually decided to create.

Now run that forward across a year of helpful AI commits. The bill arrives as inconsistent behavior, as maintenance that has to be performed several times in several places by someone who can find all of them, and as the slow erosion of your belief that the codebase has one correct way to do anything. It stops having one, so the belief was right to leave.

What to actually do about it

You do not fix this by asking everyone to be more careful, which is the programming equivalent of asking the weather to be nicer. You fix it by giving whatever writes the code a way to know what already exists.

That is the entire reason I built DRY.codes.

DRY.codes indexes the repositories you connect, across your personal account and your organizations, and builds two things from them. The first is a fast, searchable memory of every file you have already written. The second is a precomputed map of where your code already repeats itself, file pairs ranked by how much they actually share. It then exposes all of it over the Model Context Protocol, which is the part that matters, because MCP is the letterbox through which your AI assistant finally gets to see the rest of the house.

So the contractor who forgets everything gets a memory. Before writing a new helper, an agent can search the knowledge base for one that already does the job. It can locate a file by name, compare two files to decide whether a near-duplicate is worth consolidating, and run a snippet through dry_wand to ask, in effect, "have we written this already?" The answer arrives before the duplicate does, which is the only time the answer is useful.

You can point it at a single repository or an entire organization to see the worst duplication hotspots and decide what to refactor first. You can keep shared configuration and utilities honest across dozens of projects at once. And if you live in Claude Code, the plugin wires this straight into your workflow with a "reuse before you write" reflex, so the search happens by default rather than by virtue. There is even a public corpus at dry.codes/mcp/public if you want to feel the idea before connecting anything of your own.

The point is not to scold the model. The point is to hand it the one thing it was missing.

The cheerful twist

DRY did not become less important when machines learned to write code. It became more important, and it became democratic. The duplication problem that used to belong exclusively to large organizations now belongs to anyone with an AI assistant and an afternoon.

The happy part is that the same tools generating all this duplication are perfectly capable of avoiding it, the moment you give them some memory of the code that is already sitting right there.

Write it once. Then make sure everything, human and machine alike, can actually find it. That last sentence used to be advice. With DRY.codes, it is just how the tooling works.

Follow quotentiroler on GitHub