Feature Envy

Compare
Symptom
Human

A method on class A reaches deeply into class B's data via getters, then computes something B should compute. The reader's rises because the logic's location (class A) doesn't match its subject (class B's fields); the of holding both class shapes in mind compounds across every read.

Agent

A method's body references foreign-class data more than its own; the agent loading this method also loads the foreign class to verify any change. The agent's doubles for what reads as one operation, and the of pulling B's surface into reasoning about A's method pays no information dividend.

Goal
Human

Methods live with the data they care about — B owns the logic over B's fields, in line with at the class boundary. Readers find the calculation where the data sits; B's public surface shrinks to what callers actually need, and A no longer reaches across to assemble a B-shaped answer.

Agent

Method bodies stay close to the data they read — the agent loads one class to reason about one behavior. The agent's holds the class that owns both the data and the calculation; the count drops because the agent doesn't jump between two surfaces to assemble the meaning of one method.

Smellier version

class Order {
totalWeight() {
return this.items.reduce((s, i) => s + i.unitWeight * i.qty, 0);
}
}

Fresher version

class Item { weight() { return this.unitWeight * this.qty; } }
class Order { totalWeight() { return this.items.reduce((s, i) => s + i.weight(), 0); } }
Example source: Illustrative example written for this site, not a quotation from any source.
Pressure
Human

Domain logic lives where it's least expected; B's internals leak through public surfaces just to support A's method, and any change to B's representation cascades to A. The of a B-side rename or refactor stretches into A's body; reviewers verifying the change inspect two classes instead of one.

Agent

Each call to the envious method pulls a second class into the agent's working context; chained reasoning across the boundary compounds the load. The agent's rises because verifying the method requires verifying invariants on B that A's caller can't see; an edit to B's representation surfaces only after a downstream test fails.

Tradeoff
Human

Moving the method may pull collaborators with it — A's other internals that the moved method referenced now travel too, or get passed in as parameters. Sometimes the move uncovers a missing third class. The team's reshapes rather than vanishes; the new home for the logic may surface coupling the old position concealed.

Agent

Moving the method may force additional cross-class dependencies the original boundary hid; the agent verifying the move traces the new coupling at the destination class. The agent's rises during the move itself — every caller must be updated, and the agent re-reads each site to confirm the dispatch now points at B.

Relief
Human

Encapsulation tightens, getters can shrink or disappear, and the method's name clarifies once it's on the right class. The team's drops because B-side changes now stay inside B; the team's also drops because adding a new B-derived value is one edit on B rather than a coordinated change across A and B.

Agent

The method's data sits inside the agent's current reasoning context; verifying behavior touches one class instead of two. The agent's per edit drops because the relevant surface fits in one read, and the of cross-class reasoning disappears — invariants on B's fields are checkable from B's body alone.

Trap
Human

Moving every method that reads another class's data — even legitimate cross-class queries — over-tightens encapsulation and forces a fan-out of moves that breaks the original design's intent. The cure adds as classes acquire methods they wouldn't have grown on their own, and the team chases the move across every collaborator.

Agent

Mechanical move-the-method-to-the-data on every cross-class read creates a fan-out the agent follows at every call site — the cure becomes a worse smell than the original. Context-window load now rises on B's class as it accumulates methods that belong elsewhere; B becomes a god-class the agent loads as a tangle.