Two or more classes in the codebase do similar work but use different method names, parameter shapes, or return types for the same operation. The divergence is accidental — they were written at different times by different people. Callers can't treat them uniformly; tests for each one duplicate setup; cross-class refactoring requires synchronized edits.
Operations with the same semantics carry different names across N classes; a grep for one name returns one class's call sites, missing the aliases; the agent enumerating consumers pays the cost of knowing the alias map for the operation.
All variants share one method-name vocabulary for the same operations. Callers operate against either interchangeably; tests can share helpers; future variants land with the same vocabulary.
Each operation has one name across every class that exposes it; a grep for the name returns every call site, and the agent enumerates consumers without paying for an alias map.
Before the refactoring
// Two repositories do the same work with accidentally divergent names.class UserRepository {findOne(id) { /* ... */ }insert(user) { /* ... */ }updateById(id, fields) { /* ... */ }remove(id) { /* ... */ }}class OrderRepository {getById(id) { /* ... */ }create(order) { /* ... */ }update(id, fields) { /* ... */ }delete(id) { /* ... */ }}function loadEntity(repo, id) {if (repo instanceof UserRepository) return repo.findOne(id);return repo.getById(id);}
After the refactoring
// One method name per operation; both repositories conform.class UserRepository {findById(id) { /* ... */ }create(user) { /* ... */ }update(id, fields) { /* ... */ }delete(id) { /* ... */ }}class OrderRepository {findById(id) { /* ... */ }create(order) { /* ... */ }update(id, fields) { /* ... */ }delete(id) { /* ... */ }}function loadEntity(repo, id) {return repo.findById(id);}
Accidental interface divergence is a tax on every consumer that handles both. The divergence often grew from copy-paste with renames; each rename created another inconsistency to navigate. Reviewers and agents must remember which class uses which name.
Inconsistent naming forces the agent to enumerate aliases on every cross-class change. The cost compounds — `find usages` returns partial results; semantic edits miss aliased variants; the agent's confidence in completeness drops.
Renaming methods is a wide ripple — every call site moves. For classes with public APIs or vendor consumers, the breaking-change cost may exceed the consistency gain. Sometimes a single adapter call site is cheaper than a rename across N consumers.
Renames break external consumers who depend on the old names; the agent must verify the rename's blast radius before applying it. For library code with documented APIs, the rename cost may exceed the consistency gain.
One vocabulary, one call shape, one set of tests' helpers. Future variants land with the established names; new consumers don't have to learn which-name-here-and-which-name-there.
Edits to the operation's contract land against one name across every class; tooling that searches by name returns every call site, and the agent does not pay the alias-mapping cost on cross-class changes.
Forcing two genuinely-different operations onto the same name to satisfy the pattern produces silent behavioural drift — the names match but the semantics differ. Unify Interfaces is for accidental divergence; if the operations actually behave differently, they should keep different names.
Unifying names across two classes whose operations only superficially match silently misleads future readers. The agent reads `findById` on both and assumes equivalent behaviour; when one has implicit side effects the other doesn't, the trap is hard to detect statically. Verify behaviour matches before unifying names.