web-dev-qa-db-ja.com

「機能羨望の」コードとは何ですか。なぜコード臭と見なされるのですか?

この SOに関する質問 は、OPの考えを修正することについて話しますfeature envyコード。この気の利いたフレーズが引用されているのを私が見た別の例は、programmers.SEの 最近ここで回答 にあります。私は コメント に立ち寄って情報を求めましたが、Q&Aをフォローしているプログラマーが機能の意味を理解するのに一般的に役立つと思いました-envy。適切と思われる場合は、追加のタグを自由に編集してください。

57
Geek

Feature envy は、あるオブジェクトが別のオブジェクトのフィールドに到達して、オブジェクトに計算を依頼するのではなく、ある種の計算を実行したり、決定を下したりする状況を表す用語です自体。

ささいな例として、長方形を表すクラスを考えます。長方形のユーザーは、その領域を知る必要がある場合があります。プログラマーはwidthおよびheightフィールドを公開し、Rectangleクラスの外部で計算を行うことができます。または、Rectanglewidthおよびheightフィールドを非公開にして、getAreaメソッドを提供することもできます。これは間違いなく優れたアプローチです。

最初の状況の問題、およびコードの臭いと見なされる理由は、カプセル化が壊れているためです。

経験則として、別のクラスのフィールドを広範囲に使用してあらゆる種類のロジックまたは計算を実行する場合は、そのロジックをクラス自体のメソッドに移動することを検討してください。

96
jhewlett

別のクラス/構造体のメソッドを広範囲に使用しても問題がない場合-クラス/構造体がデータのコンテナである場合。通常、外部コンテキストなしでこのデータを使用してできることはほとんどありません。

そのようなクラスは依然としていくつかの内部ロジックを保持できますが、多くの場合、それらはコンテナーとして使用されます。

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はこの記事を参照して、他のクラスメンバーを広範囲に使用するべきではないことを証明していますが、そこに私の例を支持する別のコードのにおい状況が記載されています:

長いパラメータリスト。特定のメソッドで必要なパラメーターの数を制限するか、オブジェクトを使用してパラメーターを結合します。

1
Riga