web-dev-qa-db-fra.com

Qu'est-ce qu'un code "envie de fonctionnalités" et pourquoi est-il considéré comme une odeur de code?

Cette question sur SO parle de la correction de ce que le PO pensait du code d'envie . Un autre exemple où j'ai vu cette phrase astucieuse citée est dans un réponse récemment donnée ici dans programmers.SE. Bien que j'aie ajouté un commentaire à cette réponse en demandant les informations, je pensais que cela aiderait les programmeurs à suivre les questions et réponses pour comprendre ce que l'on entend par le terme . -envy . N'hésitez pas à modifier des balises supplémentaires si vous le jugez approprié.

57
Geek

Feature envie est un terme utilisé pour décrire une situation dans laquelle un objet atteint les champs d'un autre objet afin d'effectuer une sorte de calcul ou de prendre une décision, plutôt que de demander à l'objet de faire le calcul lui-même.

Comme exemple trivial, considérons une classe représentant un rectangle. L'utilisateur du rectangle peut avoir besoin de connaître sa zone. Le programmeur peut exposer les champs width et height puis effectuer le calcul en dehors de la classe Rectangle. Alternativement, Rectangle pourrait garder les champs width et height privés et fournir une méthode getArea. C'est sans doute une meilleure approche.

Le problème avec la première situation, et la raison pour laquelle elle est considérée comme une odeur de code, est qu'elle rompt l'encapsulation.

En règle générale, chaque fois que vous vous retrouvez à utiliser largement les champs d'une autre classe pour effectuer toute sorte de logique ou de calcul, envisagez de déplacer cette logique vers une méthode sur la classe elle-même.

96
jhewlett

Il y a une situation possible quand il est OK d'utiliser intensivement une autre méthode class/struct - quand votre classe/struct est un conteneur de données. Habituellement, vous pouvez faire un peu avec ces données sans contexte externe.

Ces classes peuvent toujours contenir une logique interne mais le plus souvent, elles sont utilisées comme conteneurs:

class YourUid {
 public:
  YourUid(int id_in_workplace_, int id_in_living_place_, DB* FBI_database, int id_in_FBI_database);
  bool IsInvalidWorker() const { return id_in_workplace == consts::invalid_id_in_workplace; }
  bool CanMessWith() const { return !FBI_database_.is_cool(id_in_FBI_database_); }
  int id_in_workplace;
  int id_in_living_place;
 private:
  int id_in_FBI_database_;
  const DB* FBI_database_;
};

@jhewlett dans sa réponse se réfère à cet article pour prouver que vous ne devez pas utiliser d'autres membres de la classe, mais il y a une autre le code sent situation décrite ici avec les avocats de mon exemple:

Liste longue des paramètres. Limitez le nombre de paramètres dont vous avez besoin dans une méthode donnée ou utilisez un objet pour combiner les paramètres.

1
Riga