Что такое код «зависти к особенностям» и почему он считается запахом кода?

53

Этот вопрос о SO говорит о том, чтобы исправить то, что OP считал кодом зависти к функциям . Другой пример, где я видел, как цитируется эта изящная фраза, - недавно полученный ответ здесь, в programmers.SE. Несмотря на то, что я добавил комментарий к этому ответу с просьбой предоставить информацию, я подумал, что она поможет программистам после Q & A понять, что означает термин « зависть к функциям» . Пожалуйста, не стесняйтесь редактировать дополнительные теги, если считаете нужным.

Компьютерщик
источник

Ответы:

88

Зависть к характеристикам - это термин, используемый для описания ситуации, в которой один объект попадает в поля другого объекта для выполнения какого-либо вычисления или принятия решения, вместо того, чтобы просить объект выполнить само вычисление.

В качестве тривиального примера рассмотрим класс, представляющий прямоугольник. Пользователь прямоугольника, возможно, должен знать его площадь. Программист может выставить widthи heightполя, а затем выполнять вычисления вне Rectangleкласса. С другой стороны , Rectangleможет держать widthи heightполе частными и обеспечивает getAreaметод. Это возможно лучший подход.

Проблема с первой ситуацией, и причина, по которой это считается запахом кода, заключается в том, что он нарушает инкапсуляцию.

Как правило, всякий раз, когда вы обнаруживаете, что интенсивно используете поля из другого класса для выполнения какой-либо логики или вычисления, рассмотрите возможность перемещения этой логики в метод самого класса.

jhewlett
источник
7
+1, хотя ваш пример нереалистичен, поскольку полезный класс Rectangle обычно предоставляет поля ширины и высоты.
Док Браун
2
И хотя нарушение инкапсуляции может происходить вместе с «Зависанием свойств», в большинстве реальных примеров, которые я видел до сих пор, это, вероятно, было не так. Это случается чаще в ситуациях «эй, мне нужно вычислить некоторые вещи только в коде, используя этот объект, и я не уверен, могу ли я коснуться реализации этого объекта / если мы должны дать объекту ответственность за эти вычисления». И затем каждый реализует вычисление, используя поля, которые уже выставлены (хотя в объекте, возможно, была бы намного более чистая реализация).
Док Браун
2
@DocBrown Представьте себе прямоугольник, нарисованный на поверхности тора, конуса или сферы. Если моя библиотека для рисования фигур создает объекты, которые способны давать правильные результаты в таких контекстах, вы были бы глупы не оставлять их для вычисления своих собственных областей - в любом контексте.
Брюс
1
@ OskarN .: По определению речь идет о функциях, которые необходимы. Они, очевидно, необходимы, если другие классы повторно реализуют их снова и снова.
Aaronaught
1
@ OskarN .: это зависит; иногда решение ясно, иногда дело вкуса, а чаще всего дело опыта. В вашей статье есть веские причины, по которым Скотт Мейерс пишет: « иногда меньше значит больше», и что ему потребовались годы, чтобы понять, когда не следует применять его «алгоритм для принятия решения, когда выполнять функцию-член fa».
Док Браун
1

Возможна ситуация, когда можно нормально использовать другие методы класса / структуры - когда ваш класс / структура является контейнером для данных. Обычно есть немного, что вы можете сделать с этими данными без внешнего контекста.

Такие классы могут все еще содержать некоторую внутреннюю логику, но чаще они используются в качестве контейнеров:

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
как это отвечает на заданный вопрос?
комнат
@gnat Вопрос о том, почему это считается «запахом кода». Jhewlett дает A с некоторыми слишком общими предположениями, поставленными под сомнение в комментариях. Мой ответ - 2 цента, чтобы отличить «запах кода» от обычной практики.
Рига,