Це запах коду, якщо приватний метод викликає загальнодоступний?


25

Чи викликає запах коду загальнодоступний метод в приватному методі того ж об'єкта екземпляра?


AAMOI, чи є у вас конкретний приклад?
ocodo

Ні, зараз. Щойно згадав випадок, який я обговорював з колегами. Хотіли отримати тут і деякі думки.
Еймантас

5
Зазвичай я можу розібратися в абревіатурі за контекстом, але AAMOI мені точно довелося шукати
Карсон Майєрс

@Carson - ти щось знайшов?
Еймантас

4
Як питання цікавого
Карсон Майєрс

Відповіді:


32

Ніякого неприємного запаху. Це може знадобитися, чому ви підозрюєте, що це неправильно? Метод на атомному рівні - це незалежна сутність, яка виконує завдання. Поки він виконує завдання, кожен, хто має доступ до нього, може зателефонувати, щоб виконати завдання.


Я згоден. Деякі методи забезпечують функціональність, яка корисна як для внутрішніх, так і для зовнішніх абонентів. Червоний прапор може бути, якби загальнодоступний метод був дуже специфічним для внутрішньої реалізації, але навіть тоді не кожен клас має намір приховати свої внутрішні. Наприклад, у мене часто є шар "інструменту" структури даних під шаром абстрактного типу контейнера - таким чином я можу повторно використовувати частину коду структури даних для інших структур даних, що лежать в основі інших контейнерів.
Стів314

19

Кодовий запах? Так, не дуже поганий, але хороший показник того, що клас може мати занадто багато обов'язків.

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

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

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


5
+1 для "не привід для тривоги". Занадто багато разів ми бачимо «запах» і миттєво переходимо в режим рефактора, не замислюючись.
Майкл К

+1 для SRP. Я просто натрапив на випадок, коли декоратор не працював, тому що оформлений клас викликав свою власну публічну функцію, минаючи декоратора. Рішення: розбийте клас на два та введіть оформлену залежність.
Джон Хулка

18

Це може призвести до неприємних сюрпризів, якщо хтось, хто не прочитав вихідний код цього класу, намагається підкласифікувати його і замінити відкритий метод. Чи справді це справді хвилює, очевидно, залежить від вашої ситуації. Можливо, вам варто подумати про те, щоб зробити загальнодоступним метод або навіть підсумковий клас.


Чому? Якщо переписаний публічний метод призводить до неприємних сюрпризів, чи справді має значення хто назвав метод?
користувач281377

4
Так. Якщо переосмислення одного публічного методу порушує інший публічний метод, я також можу змінити цей інший метод. Якщо це порушує приватний метод, я можу ....?
Кім

5
Неприємний сюрприз, що виникає внаслідок перекриття публічного методу, - кодовий запах сам по собі. Справді кодовий сморід.
Ларрі Коулман

Кім: якщо метод є загальнодоступним, ви повинні припустити, що інші класи називають цей метод так само добре ...
user281377,

@Larry: Саме так! Приватний метод (який зазвичай містить припущення щодо конкретного впровадження), що викликає загальнодоступний, робить більш імовірним, що перекриття публічного методу може порушити справи.
Кім

5

Я не думаю, що ми можемо генералізувати.

Все дуже сильно залежить від контексту.

Можливо, скажімо, метод публічної корисності в класі, який використовують інші класи, а також якийсь приватний метод того ж класу.


5

Ні. Що ще слід зробити в цьому випадку? Зробити приватний метод загальнодоступним чи публічний метод приватним? Скопіювати-Вставити код із загальнодоступного методу в приватний?


Або дозволити публічний метод делегувати приватному (новому) приватному методу, на який викликається інший приватний метод. Але, навіщо турбуватися?
Лоуренс Дол

4

НІ , тут неприємного запаху.

якщо ми реалізуємо інтерфейс черги зі списком, чи неприємний запах просто викликати належні функції списку, щоб легко досягти реалізації черги?

якщо у вас є щось, і ви хочете перетворити це на щось інше (наприклад, обгортку), тоді його неприємний запах, його повторне використання коду з дизайнерським малюнком, що діє на рівні функцій (це функція об'єкт?)


2

Я знаю, що це стара публікація, але це щось, про що я дискутував на роботі. Я "вважаю" це кодовим запахом, і не можу зрозуміти, чому б вам хотілося це робити. Якщо приватний метод повинен викликати загальнодоступний метод, то зміст публічного методу слід приймати і розміщувати в приватному методі, який потім можуть викликати обидва методи. Чому?

  1. Загальнодоступний метод може містити тести, які не потрібні, коли ваш внутрішній код виконуватиметься. Він може отримати UserObj і, наприклад, перевірити дозволи користувача.

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

  3. На мою думку, більше шансів ввести кругові помилки та нескінченні петлі та поза винятками пам’яті.

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


1
Що робити, якщо існуючий публічний метод називається багатьма іншими класами? Якщо зробити це приватним, це порушить це. Пам’ятайте, що публічні методи називаються іншими класами з інших причин, а не тільки цього класу. чомусь існують публічні методи.
Майкл Дюрант

Я заявив, що "зміст публічного методу слід приймати і розміщувати в приватному методі ..." Публічний метод залишиться, але зателефонуйте до нового приватного методу. Як і будь-які інші приватні методи, яким потрібно повторно використовувати той самий функціонал.
Марк Грем

Тож ви додаєте інший метод ні з якої іншої причини, ніж - ну, тому що ви оголосили це "запахом коду". Безглузді методи - це гірший кодовий запах.
gnasher729

Вибачте, але хіба я не просто перерахував кілька причин вище. Багато коду, який я пишу, призначений для бізнес-систем, багато класів обмежені для користувачів залежно від ролі. Багато публічних методів перевіряють користувацькі дозволи та парами. Чому на землі я б хотів передзвонити цей же загальнодоступний метод, щоб повторно використовувати його функціональність та повторно перевірити права користувача?
Марк Грем

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

2

Уявіть навпаки. Ви користуєтеся приватним методом і вам потрібна функціональність у відкритому методі Що робити, якщо ви не змогли викликати цей публічний метод із приватного. Що б ти зробив?

  • Створити дублікат приватного методу? Ні
  • Створити спеціальний публічний метод на випадок? Ні
  • Викликати спеціальний приватний метод, який може викликати загальнодоступні методи? Ні
  • Якийсь супер, який може це зробити? Ні

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


1

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

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

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


1

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

(a) викрити щось публічно, що повинно бути приватним; або

(b) поведінка класу недостатньо вузька (продумайте принцип єдиної відповідальності).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.