A class carries several near-identical methods that differ only by a single literal — a field name, a constant, a threshold. The duplication is mechanical; the methods change in lockstep; the class grows linearly with the number of variants supported.
N near-duplicate method definitions the agent must verify match on every edit. The single difference between them is mechanical; the rest is copy-pasted. The agent must re-read all N to verify a change in one was correctly propagated.
One parameterized method replaces the N variants. What varies between them becomes an explicit argument; what stays the same lives in one place.
One method the agent reads once; callers supply the varying value at the call site. Verification of behaviour reduces from N×assertion to 1×assertion + parameter coverage tests.
Before the refactoring
// Three near-identical methods, differing only by which book field they search.class BookSearch {constructor(repo) {this.repo = repo;}searchByAuthor(query) {return this.repo.where(book => book.author.toLowerCase().includes(query.toLowerCase()));}searchByTitle(query) {return this.repo.where(book => book.title.toLowerCase().includes(query.toLowerCase()));}searchByPublisher(query) {return this.repo.where(book => book.publisher.toLowerCase().includes(query.toLowerCase()));}}
After the refactoring
// One method; the varying field is a parameter.class BookSearch {constructor(repo) {this.repo = repo;}searchBy(field, query) {return this.repo.where(book => book[field].toLowerCase().includes(query.toLowerCase()));}}
Each duplicated method must be maintained, tested, and documented separately. A bug in the iteration semantics requires N edits; adding a new variant means another near-copy, not new logic. Reviewers must scan all N methods to confirm they stayed consistent.
Per-method duplication multiplies the agent's edit cost on every shared-logic change. The agent's static reasoning cannot guarantee that N copies of a closure stayed identical without re-inspecting each.
Parameterized methods can become call-site noise — the caller now passes a string or constant whose meaning isn't clear from the call site (`searchBy('author', q)` reads worse than `searchByAuthor(q)`). For two or three variants with stable, semantically distinct names, separate methods may be more intention-revealing.
A parameterized method obscures static call-graph analysis — the agent cannot tell from the call site alone which behaviour fires. Stringy parameters (`'author'`) defeat static type-checking; misspellings ship to runtime.
Bug fixes land once; new variants are zero new code at the class level; tests cover the parameterized method once and trust the parameter to do its job. The class's surface contracts to the actual behaviours it offers.
Shared logic lives at one method body the agent reads once; the parameter holds the per-call variation, and tests cover the variants through a table the agent reads as one block instead of N near-identical test methods.
A parameter that is really a type code — `searchBy(field, q)` where `field` must be one of three strings — replaces compile-time clarity with runtime stringy-ness. Past a small number of values, this is a signal to reach for Replace Type Code With Class or Strategy.
Replacing N methods with a method that takes a stringy parameter pushes the type information out of the type system and into runtime. The agent must verify caller intent by tracing the literal across files, which costs more context than reading N distinct method names.