# Feature EnvyA intermediate-level guide to Feature Envy: before-and-after java code and diagrams for a CS student.

## The Nosy Neighbor in Your Code

Imagine you have a neighbor who doesn't just wave hello when they pass your house; instead, they lean over the fence to peek through your windows, check if you turned off the stove, and verify that your front door is locked. They are constantly gathering details about your private life just to perform simple tasks that you could easily handle yourself.

In software development, this "nosy neighbor" behavior manifests as a code smell known as **Feature Envy**. This happens when a method seems more interested in the data of another class than the data of the class it actually belongs to. Instead of asking an object to perform an action, the method pulls out all the internal details using getters and performs the logic itself.

This leads to two major architectural problems:
1.  **Low Encapsulation:** Encapsulation is the principle of bundling data with the methods that operate on that data and hiding the internal state. Feature Envy breaks this by exposing raw data for external manipulation.
2.  **High Coupling:** Coupling describes how dependent two classes are on each other. When `PayrollService` knows exactly how to calculate pay using the internals of `Employee`, they become tightly intertwined.

The following example shows a `PayrollService` that is overly obsessed with the internal state of an `Employee` object:

```java
class Employee {
    private final double hourlyRate;
    private final int hoursWorked;

    public Employee(double hourlyRate, int hoursWorked) {
        this.hourlyRate = hourlyRate;
        this.hoursWorked = hoursWorked;
    }

    public double getHourlyRate() {
        return hourlyRate;
    }

    public int getHoursWorked() {
        return hoursWorked;
    }
}

class PayrollService {
    // Feature Envy: This method is overly interested in the internal state of Employee,
    // performing calculations that should belong to the data owner.
    public double calculatePay(Employee employee) {
        return employee.getHourlyRate() * employee.getHoursWorked();
    }
}
```

```mermaid
classDiagram
    class PayrollService {
        +calculatePay(employee) double
    }
    class Employee {
        -hourlyRate: double
        -hoursWorked: int
        +getHourlyRate() double
        +getHoursWorked() int
    }
    PayrollService ..> Employee : uses getters to access data
```

## Fixing Envy with Move Method

To fix Feature Envy, we use a refactoring called **Move Method**. We identify the logic that is "envious" of another class's data and move that entire behavior into the class that actually owns that data. In our case, `Employee` is the "Information Expert"—it knows its own rate and hours, so it should be the one responsible for calculating its pay.

```java
class Employee {
    private final double hourlyRate;
    private final int hoursWorked;

    public Employee(double hourlyRate, int hoursWorked) {
        this.hourlyRate = hourlyRate;
        this.hoursWorked = hoursWorked;
    }

    // The logic is moved here to respect encapsulation.
    public double calculatePay() {
        return this.hourlyRate * this.hoursWorked;
    }
}

class PayrollService {
    public double processPayroll(Employee employee) {
        // Service now delegates the calculation to the expert (the Employee class).
        return employee.calculatePay();
    }
}
```

By moving the calculation logic into the `Employee` class, we restore proper encapsulation. Now, if the way we calculate pay changes (for example, adding overtime rules), we only have to modify the `Employee` class. The `PayrollService` no longer needs to know *how* the pay is calculated; it simply asks the expert to do its job.

```mermaid
sequenceDiagram
    participant PS as PayrollService
    participant E as Employee
    PS ->> E: calculatePay()
    E ->> E: uses hourlyRate and hoursWorked
    E -->> PS: return result
```

## When to Use It, and When Not To

Moving methods is a powerful way to clean up code, but it should be applied with intention. 

**Use Move Method when:**
*   A method calls many getters on another object while calling very few of its own fields.
*   You notice "Data Classes"—classes that contain only fields and getters but no actual behavior. Moving logic into these classes turns them from simple data containers into robust, encapsulated objects.

**Avoid Move Method when:**
*   Moving the method would create a "God Object" (a single class that knows too much or does too much). If you move every piece of logic to one class, you violate the Single Responsibility Principle.
*   The logic requires many parameters from the original class to function; in those cases, moving the method might result in an overly complex dependency.

## Takeaways

- Feature Envy occurs when a method relies heavily on the getters of another object to perform its work.
- Use the **Move Method** refactoring to shift logic to the "Information Expert" (the class that owns the data).
- Proper encapsulation makes your code more resilient; changing an internal field only requires updates in one place rather than across many service classes.

## Usage

**Using the refactored design to calculate pay**

```java
Employee emp = new Employee(50.0, 40);
PayrollService service = new PayrollService();
double pay = service.processPayroll(emp); // 2000.0
```
