A large rock or very small island with a few green shrubs growing on it surrounded by greeny blue water and white surf.
Unrelated image from pexels.com to make this post look nicer in social media shares.

Today’s code smell is feature envy. Feature envy is when one class uses the methods of another class to excess. It’s called feature envy because classes that use methods from another class excessively look envious of that class’s features.

The problem with that, as usual, is the way your logic gets spread around between multiple classes. If you have one method that’s using another class so much that it’s hardly even separate from it, you’ll probably have to change things in both places when you need to fix a bug or add a new feature, but the compiler can’t tell you that you need to do that so you risk creating a shiny new bug by missing a spot.

Feature envy probably makes more sense with an example. Let’s say you have an address class and a customer class, and when you call customer.getMailingLabel() your customer class calls address.getStreetNumber(), address.getStreetName(), address.getCity() and so on to build a complete address string for printing a mailing label. Let’s imagine that policy changed and you’re now able to ship to rural mailboxes, so you need to add route and box numbers to your address and to use those instead of street number and street name if they’re present. If your code has feature envy, you have to change both the address object and the getMailingLabel method to support rural mailboxes. If you moved the getMailingLabel method into the address class, then you would only have to change one class when you wanted to change how you build mailing labels.

As with just about all code smells, feature envy isn’t always a sign there’s a problem. Sometimes you want to separate your data from operations on it, especially if you’re using a strategy or visitor design pattern. If, for example, you want addresses formatted differently for different reports, the formatting is probably more the job of the reporting code than the address object. In that case it would make more sense for a visitor to contain the formatting code so the address object doesn’t have to care about all the different reports.