Two classes the agent recognizes as doing similar things but with mismatched method names and signatures; the agent must learn both vocabularies and translate between them.
Equivalent operations have equivalent signatures; the agent uses one mental model and the type system enforces substitutability.
Smellier version
class CSVExporter { writeAll(rows) {} }class JSONExporter { dump(data) {} }
Fresher version
class CSVExporter implements Exporter { write(rows) {} }class JSONExporter implements Exporter { write(rows) {} }
Substitution becomes copy-paste; abstraction over the two is impossible; the agent must hold both interfaces in working memory to use either.
Aligning the interfaces forces renames across both classes and every consumer; the agent verifying the alignment must update every call site and confirm the new common contract holds for both.
A shared interface lets the agent dispatch through one type signature instead of loading both class surfaces; new alternatives plug into the interface, and consumer code generalizes across them without per-class branching.
Forcing two classes into a shared interface despite genuinely different contracts produces an abstraction the agent must constantly special-case — important distinctions hide behind a fake polymorphism.