Feature Envy
Feature Envy is a method fixated on another class's data, reaching in through getters instead of letting that class act. Move the behavior to the data's owner and apply Tell, Don't Ask to restore encapsulation and cut coupling.
Feature Envy is a method that seems more interested in the data of another class than in its own. It repeatedly calls getters on some other object, pulls out its fields, and computes a result that really belongs to that other object. The method 'envies' the features of the class whose data it keeps borrowing.
Why It Happens
It is often easier to add a calculation to the class you are already editing than to open the class that owns the data. Anemic data classes — objects that expose fields through getters but contain no behavior — practically invite outsiders to do their work for them. Procedural habits in object-oriented code also push logic into 'manager' or 'service' methods that reach into many objects.
Why It Hurts
Logic ends up far from the data it operates on, so understanding the data class means hunting for behavior elsewhere. Encapsulation breaks: the owning class cannot enforce its own invariants because outsiders manipulate its internals. Coupling rises, because the envious method depends on the structure of the other class and breaks when that structure changes. The same calculation often appears in several envious methods, duplicating rules.
Warning Signs
- A method that calls several getters on one other object and little on
this. - Chains like
order.getCustomer().getAddress().getZip(). - Business rules implemented on another class's fields.
- 'Anemic' data classes with getters but no methods.
Better Alternatives
Apply Move Method: relocate the behavior to the class that owns the data, so it operates on its own fields. Follow Tell, Don't Ask — instead of asking an object for its data and acting on it, tell the object to perform the action. Strengthen encapsulation by giving data classes real behavior, turning anemic models into rich ones. The Law of Demeter discourages reaching through long getter chains.
How to Refactor Out of It
Find methods that touch another object's data more than their own. Move the relevant logic into that object as a new method, then have the original caller invoke it. If the method legitimately needs data from two classes, place it on the one whose data it uses most, or extract a small collaborator. Reduce getter chains by adding intention-revealing methods on the intermediate objects. After moving behavior, confirm the data class now enforces its own rules and that callers simply tell it what to do.