Методи мінімізації кількості аргументів функції


13

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

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

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

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


21
Tbh Я зовсім не згоден з чистим кодом. Якщо кількість аргументів функції дорівнює нулю, то це означає, що функція має побічні ефекти і, можливо, десь змінює стан. Хоча я згоден, що менше 4 аргументів може бути хорошим правилом - я б скоріше мав функцію з 8 аргументами, яка є статичною і не має побічних ефектів, ніж нестатична функція з нульовими аргументами, яка змінює стан і має побічні ефекти .
wasatz

4
" У чистому коді написано, що" ідеальна кількість аргументів для функції дорівнює нулю ". " Дійсно? Це так неправильно! Ідеальна кількість параметрів - одна, із зворотним значенням, яке детерміновано виходить із цього одного параметра. На практиці кількість параметрів не має великого значення; Що важливо, це те, що, коли це можливо, функція повинна бути чистою (тобто вона отримує своє повернене значення лише з її параметрів без побічних ефектів).
Девід Арно

2
Що ж, книга пізніше продовжує зазначити, що побічні ефекти небажані ...
Ніл Барнвелл


Відповіді:


16

Найголовніше, що потрібно пам’ятати, це те, що це настанови, а не правила.

Бувають випадки, коли метод просто повинен взяти аргумент. Подумайте, наприклад, про +метод числення. Або addметод для колекції.

Насправді, можна навіть стверджувати, що те, що означає додати два числа, залежить від контексту, наприклад, у ℤ 3 + 3 == 6, але в ℤ | 5 3 + 3 == 2 , тому дійсно оператор додавання повинен бути методом на контекстному об'єкті, який бере два аргументи замість метод на числах, який бере один аргумент.

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

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

  • Зробіть сам метод меншим : можливо, якщо методу потрібно стільки аргументів, він робить занадто багато?
  • Відсутня абстракція : Якщо аргументи тісно співвіднесені, можливо, вони належать разом, і є абстракція, яку ви пропускаєте? (Приклад канонічної книги з текстами: замість двох координат передайте Pointоб’єкт або замість того, щоб ввести ім'я користувача та електронну пошту, передайте IdCardоб’єкт.)
  • Стан об'єкта : Якщо аргумент потрібен декількома методами, можливо, він повинен бути частиною стану об'єкта. Якщо для цього потрібні лише деякі з методів, але не інші, можливо, об'єкт робить занадто багато і справді повинні бути два об'єкти.

Один із способів - витягнути аргументи в новий клас, але це, безумовно, призведе до вибуху класів?

Якщо у вашій моделі домену є багато різних речей, то ваш код матиме багато різних об'єктів. У цьому немає нічого поганого.

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

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

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

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

Зауважте, як часто я вживав слово "можливо"? Ось чому це правила, а не правила. Можливо, ваш метод з 4 параметрами ідеально чудовий!


7
@ BrunoSchäpper: Звичайно: (1) " Зробіть сам метод меншим: можливо, якщо методу потрібно стільки аргументів, він робить занадто багато? ". Кількість парам - це погана перевірка цього. Необов’язкові / булеві парами та багато рядків коду є сильними показниками того, що метод робить занадто багато. Багато парам є в кращому випадку слабким. (2) " Стан об'єкта: Якщо аргумент потрібен декількома методами, можливо, він повинен бути частиною стану об'єкта ". Ні, ні і тричі, ні. Мінімізація стану об'єкта; не функціональні параметри. Якщо можливо, передайте значення всім методам за допомогою параметрів, щоб уникнути стану об'єкта.
Девід Арно

Приклад, який ви подали для додавання, є неправильним. addФункція для натуральних чисел і addфункція для кільця цілих мод п дві різні функції дії на два різних типів. Я також не розумію, що ви маєте на увазі під "контекстом".
садок

Thx @DavidArno. 1) погоджений, не сильний показник сам по собі. Але хороший, тим не менше. Я часто бачу кілька методів, де кілька об'єктів пройшли навколо. Немає об'єктного стану. Це добре, але 2) кращий варіант IMHO рефакторинг цих методів, переміщення неявного стану в новий клас, який сприймає всі ці параметри як явні аргументи. У кінцевому підсумку ви знайдете один загальнодоступний метод нульового аргументу та безліч внутрішніх методів аргументу від нуля до одного. Держава не є загальнодоступною, глобальною або навіть довго зберігається в живих, але код набагато чистіший.
Бруно Шепер

6

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

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

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

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

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


1
Як і ваша аналогія "фокусування об'єктива" - Особливо під час рефакторингу важливо використовувати ширококутний об'єктив замість крупного плану. А
вивчити

0

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

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

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

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


5
Звичайно, сліпо зменшити кількість аргументів неправильно. Але я не погоджуюся з тим, що "у функцій, що мають велику кількість аргументів, немає абсолютно нічого поганого". . На мою думку, коли ви потрапляєте на функцію з великою кількістю аргументів, у 99,9% всіх випадків є спосіб навмисно поліпшити структуру коду, що (також) зменшує кількість аргументів функції.
Doc Brown

@DocBrown Ось чому є цей останній абзац і рекомендація починати з нього .... І ще один: Ви, напевно, ніколи не намагалися програмувати проти MS Windows API;)
tofro

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

1
@NeilBarnwell В ідеальному випадку (варто рефакторингу) ви можете розбити функцію, якій потрібно 10 аргументів на три, для цього потрібно 3-4 аргументи. У випадку не дуже ідеального випадку ви закінчуєтесь трьома функціями, для яких потрібно 10 аргументів (краще залиште їх у спокої). Що стосується вашої аргументації з вищим стеком: Погодьтеся - це може бути так, але необов'язково - аргументи звідкись і десь, і вилучення може бути десь усередині стека, і його просто потрібно поставити на потрібне місце там - Пробіг має тенденцію до змін.
tofro

Логіка програмного забезпечення ніколи не вимагає більше чотирьох параметрів. Лише компілятор може.
Доктор

0

Немає чарівного способу: ви повинні оволодіти проблемним доменом, щоб виявити правильну архітектуру. Це єдиний спосіб рефактора: оволодіння проблемною областю. Більше чотирьох параметрів - це просто впевнена ставка, що ваша поточна архітектура несправна і неправильна.

Виняток становлять лише компілятори (метапрограми) та моделювання, де теоретично межа становить 8, але, ймовірно, лише 5.

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