Чи корисні необов'язкові параметри чи перешкоджають обслуговуванню додатків? [зачинено]


15

Як зазначено в заголовку, чи не корисні параметри, наприклад ті, що використовуються в C #, або вони перешкоджають обслуговуванню додатків, і їх слід уникати, оскільки вони можуть зробити складніше зрозумілий код?


3
Відмова від відповідальності: будь-якою мовною функцією в чужих руках можна зловживати. Якщо мова реалізує це розумно, а ця мовна функція не перегукується занадто сильно з існуючою мовною функцією, то вони просто чудові, насправді досить корисні. У Python є кілька акуратних упаковок / розпакування парам та інших параметрів "трюки" (хитрощі в хорошому, а не в сенсі Perl).
Робота

Спробуйте написати додаток у C #, який інтерфейсує в Excel, не використовуючи додаткові параметри. Це повинно відповісти на ваше питання поза будь-якими розумними сумнівами.
Данк

Відповіді:


22

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

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


1
+1 І це цінно завдяки перевантаженим методам, які додають такий аргумент, як, new Circle(size, color, filled, ellipseProportions)де sizeі colorпотрібно, а решта - за замовчуванням.
Майкл К

15

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

Шукайте параметри, які можна згрупувати, наприклад (x і y, станьте точкою).

Чи є ці необов'язкові параметри прапорцями за замовчуванням? Якщо ви використовуєте прапори, функцію слід розділити.

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

Це також може бути підказкою, що функція насправді повинна бути класом із необов'язковими параметрами, зміненими на властивості, а необхідні параметри - частиною конструктора.


1
+1 за обережність. Будь-якою особливістю, незалежно від того, наскільки добре, можна зловживати.
Майкл К

3
Це чудова порада для створення перенапруженого коду равіолі, коли користувачі вашого API повинні використовувати щонайменше 6 класів та 15 функцій, щоб зробити навіть найпростішу річ.
dimimcha

1
@dsimcha, як ти це отримуєш з того, що я написав? Ого. Будь ласка, поясніть? Це було б настільки ж погано, щоб мати "суперфункцію", яку ви отримуєте, коли у вас є безліч додаткових параметрів. Читайте про принципи дизайну SOLID та написання тестового коду. Переважно з використанням TDD. Потім поверніться і спробуйте пояснити мені, що зменшення параметрів у функціях - це погано.
CaffGeek

1
Тестовий код є приємним, але це чистий, корисний API, який не є надмірно дрібним або багатослівним і не вбирає класи в ситуації, коли функцією є правильна абстракція. Я вірю в єдиний принцип відповідальності з обов'язками, визначеними на високому рівні абстракції. Якщо відповідальність визначена на занадто низькому рівні, окремі підрозділи стають надто спрощеними, щоб їх взаємодія надмірно складна.
dimimcha

1
@dsimcha, ви пропускаєте суть. Окремі одиниці повинні залишатися окремими одиницями, а не згуртовуватися в одну функцію. Це також не означає, що всі вони є загальнодоступними функціями. Ви API - це шлюз до коду, і він повинен бути чистим і стислим. Функція з кількома необов'язковими параметрами не є ні чистою, ні стислою. Однак перевантаження однієї функції логічними параметрами набагато зрозуміліше. Наприклад, у багатьох API є функції, де дві парми необов’язкові, але потрібна та чи інша. Що в цьому зрозуміло, коли обидва позначені як необов’язкові?
CaffGeek

4

Необов’язкові параметри просто чудові

Зазвичай виправданням є або те, що: a) ви знаєте, що у вас є багато можливих аргументів для вашого методу, але ви не хочете перевантажуватися, боячись затиснути API, або b) коли ви не знаєте всіх можливих аргументів, але ви не хочуть змушувати свого користувача надати масив. У кожному випадку необов'язкові параметри приходять на допомогу акуратно та елегантно.

Ось кілька прикладів:

1. Ви хочете уникнути перевантаження і не хочете вказувати масив

Погляньте на printf () від C, Perl, Java тощо. Це чудовий приклад потужності необов'язкових параметрів.

Наприклад:

printf("I want %d %s %s",1,"chocolate","biccies");

printf("I want %d banana",1);

Без перевантаження, без масивів, просто та інтуїтивно зрозуміло (як тільки ви зрозуміли коди стандартного рядка). Деякі IDE навіть повідомлять, чи ваш форматний рядок не відповідає вашим необов'язковим параметрам.

2. Ви хочете дозволити використання за замовчуванням і зберегти їх прихованими від користувача методу

sendEmail ("test@example.org");

Метод sendEmail виявляє, що різні істотні значення відсутні, і заповнює їх за допомогою визначених значень за замовчуванням (тема, тіло, копія, копія та ін.). API підтримується чистим, але гнучким.

Примітка про занадто багато параметрів

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

String myMethod(String x, String y, String z, String a, int b, String c, int d) {}

є ідеальним кандидатом для створення рефакторингу об'єкта введення параметра

String myMethod(ParameterObject po) {}

class ParameterObject {
  // Left as public for clarity
  public String x;
  public String y;
  ... etc

}

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


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

@Chad Я скоригував свою відповідь, щоб краще розмежувати необов'язкові параметри та коли вони переходять у запах коду (як ви вже згадували у своїй відповіді).
Гері Роу

@Gary Rowe, занадто багато необов'язкових параметрів теж погано в більшості випадків.
CaffGeek

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

@Gary Rowe, що ви маєте на увазі "більшість мов не передбачають способу визначення обмеження на кількість необов'язкових аргументів"? Більшість мов ви позначаєте їх як такі або не надаєте їм значень під час виклику функції, але заголовок функції все ще має визначені параметри. Звичайно, на деяких мовах ви можете додати стільки бажаних параметрів після того, як ви заповнили визначені, але я не думаю, що про такі необов'язкові параметри ми говоримо тут. (окрім виключення рядкового формату)
CaffGeek

2

Однією з проблем із параметрами за замовчуванням у C # (я думаю, що недійсне DoSomething (int x = 1)) - це константи. Це означає, що якщо ви зміните типовий засіб, вам доведеться перекомпілювати будь-яких споживачів цього виклику методу. Хоча це зробити досить просто, є випадки, коли це небезпечно.


1

Це залежить від вашого коду. Якщо є розумні за замовчуванням, то слід використовувати необов’язкові параметри, але якщо немає розумних значень за замовчуванням, додавання додаткових параметрів ускладнить ваш код. У багатьох випадках необов'язкові параметри є акуратним способом усунення нульових перевірок та вирізання логіки розгалуження. У Javascript немає необов'язкових параметрів, але є спосіб емуляції їх за допомогою || (логічно або), і я використовую це весь час, коли роблю речі, пов'язані з базою даних, тому що якщо користувач не надає певного значення, то я підміняю власні значення за допомогою || що врятує мені клопоту написати цілу купу, якщо тоді заяв.


1

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

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


1

Проблема з необов'язковими аргументами полягає в тому, що люди прагнуть просто підтягувати все більше (і більше) аргументів функції замість вилучення відповідного коду в нову функцію. Це до кінця в php . Наприклад:

bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
                      [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )

1

Необов’язкові параметри - це в основному інший спосіб перевантаження функції. Отже, це в основному зводиться до: "це перевантаження функції погано"?


1

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


0

Я думаю, було б краще перевантажити функцію різними підписами (тобто параметрами), ніж використовувати необов'язкові параметри.


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

Ви можете подумати про це. Мені не належить думати, що Microsoft робить все правильно, але якби ви були точні, я б ніколи не бачив перевантажень при використанні .NET-фреймворку, а лише один величезний підпис функції - як у ol 'VB6.
HardCode
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.