After reading
What is a" feature envy" code and why is it considered a code smell?"
I know the following code is suffering from "feature envy":
public class Garden{
public float width;
public float height;
}
public class Owner{
Garden garden;
public float getAddLawnCost(){
return this.garden.width*this.garden.height*LAWN_PRICE_PER_1M2;
}
}
and area of garden should be calculated inside Garden:
public class Garden{
private float width;
private float height;
public float getArea(){
this.width*this.height;
}
}
public class Owner{
Garden garden;
public float getAddLawnCost(){
return this.garden.getArea()*LAWN_PRICE_PER_1M2;
}
}
Suddenly a new requirement is added : calculate the cost of adding fence to the garden:
"Feature envy" version, class to modify : Owner
public class Garden{
public float width;
public float height;
}
public class Owner{
Garden garden;
public float getAddLawnCost(){
return this.garden.width*this.garden.height*LAWN_PRICE_PER_1M2;
}
public float getAddFenceCost(){
return (this.garden.width+this.garden.height)*2*FENCE_PRICE_PER_1M;
}
}
"non-feature envy" version, classes to modify : Owner, Garden:
public class Garden{
private float width;
private float height;
public float getArea(){
this.width*this.height;
}
public float getPerimeter(){
(this.width+this.height)*2;
}
}
public class Owner{
Garden garden;
public float getAddLawnCost(){
return this.garden.getArea()*LAWN_PRICE_PER_1M2;
}
public float getAddFenceCost(){
return this.garden.getPerimeter()*FENCE_PRICE_PER_1M;
}
}
Which the "non-feature envy" version has one extra class to modify : Garden, and hence violating "Open closed principle". Is it true?
getAddLawnCost()
andgetAddFenceCost()
. Feature envy would be something more like - suppose you had some code that had an instance of Owner, and that needed to orchestrate some calculation - but instead of Owner having these two methods, it would just have a Garden getter, and then you'd do calculations in the calling code. – Filip Milovanović Aug 08 '23 at 13:44Garden
class with the private fields violates the OCP because a certain feature cannot be implemented without modifying the class (and it is not the programmer who violates the OCP at the point in time when adding new functions to it, it is the programmer who designed the class by not providing at least public getters for width and height). – Doc Brown Aug 08 '23 at 18:19