Що таке "функція заздрості", і чому це вважається запахом коду?


53

Це запитання в ТА говорить про те, щоб виправити те, що, на думку ОП, є кодом заздрості . Ще один приклад, коли я бачив, як цитується ця витончена фраза, - це нещодавно відповідь тут у програмістах. Хоча я крапля в коментарі до цієї відповіді з проханням про інформації , яку я думав , що це було б загальної допомогу програмістам наступних Q & A , щоб зрозуміти , що мається на увазі під терміном ознака заздрості . Будь ласка, не соромтесь редагувати додаткові теги, якщо вважаєте за потрібне.


Відповіді:


88

Заздрість до функцій - це термін, який використовується для опису ситуації, в якій один об'єкт потрапляє на поля іншого об'єкта для того, щоб здійснити якесь обчислення або прийняти рішення, а не просити об’єкт зробити сам обчислення.

Як тривіальний приклад розглянемо клас, що представляє прямокутник. Користувачеві прямокутника, можливо, доведеться знати його площу. Програміст може викрити widthі heightполя, а потім зробити обчислення поза Rectangleкласом. З іншого боку , Rectangleможе тримати widthі heightполе приватними і забезпечує getAreaметод. Це, мабуть, кращий підхід.

Проблема з першою ситуацією, і причина, яку вона вважає кодовим запахом, полягає в тому, що вона порушує інкапсуляцію.

Як правило, кожного разу, коли ви широко використовуєте поля з іншого класу для виконання будь-якої логіки чи обчислень, розгляньте можливість переміщення цієї логіки до методу на самому класі.


7
+1, хоча ваш приклад не є реалістичним, оскільки корисний клас Прямокутник зазвичай виставляє поля ширини та висоти.
Док Браун

2
І хоча розрив інкапсуляції може статися разом із "Характерною енвіризмом", у більшості реальних прикладів, які я бачив до цього часу, це, мабуть, було не так. Це трапляється більше у ситуаціях, "ей, мені потрібно обчислити деякі речі просто в коді, використовуючи цей об'єкт, і я не впевнений, чи можу я торкнутися його реалізації / якщо ми повинні дати об'єкту відповідальність за це обчислення". Потім реалізується обчислення, використовуючи вже відкриті поля (хоча набагато чистіша реалізація була б можливою в межах об'єкта).
Doc Brown

2
@DocBrown Уявіть собі прямокутник, намальований на поверхні тора, конуса чи сфери. Якщо моя бібліотека малювання фігур створює об'єкти, здатні давати правильні результати в таких контекстах, вам нерозумно буде не залишати їх для обчислення власних областей - у будь-якому контексті.
йогобрюс

1
@OskarN.: За визначенням , ми говоримо про функції , які є необхідними. Вони, очевидно, потрібні, якщо інші класи знову і знову їх реалізовують.
Aaronaught

1
@OskarN .: це залежить; іноді рішення зрозуміле, іноді - питання смаку, а найчастіше - питання досвіду. У вашій статті є вагомі причини, чому Скотт Мейєрс пише " іноді менше - це більше", і що йому знадобилося років, щоб зрозуміти, коли не застосовувати його "алгоритм вирішення питання, коли зробити функцію члена члена".
Док Браун

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 дає А з деякими надто загальними припущеннями, які поставили під сумнів у коментарях. Моя відповідь - 2 копійки, щоб відрізнити "кодовий запах" від звичайної практики.
Рига
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.