Являются ли необязательные параметры полезными или препятствием для обслуживания приложения? [закрыто]

15

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

rjzii
источник
3
Отказ от ответственности: любая функция языка в чужих руках может быть нарушена. Если язык реализует это разумным образом, и эта языковая функция не слишком сильно перекрывает существующую языковую функцию, тогда они просто хороши, на самом деле весьма полезны. В Python есть некоторые аккуратные параметры упаковки / распаковки и другие «хитрости» параметров (трюки в хорошем, а не в Perl-смысле).
Работа
Попробуйте написать приложение на C #, которое взаимодействует с Excel без использования дополнительных параметров. Это должно ответить на ваш вопрос вне всякого разумного сомнения.
Данк

Ответы:

22

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

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

Дэвид Торнли
источник
1
+1 И это ценно с перегруженными методами, которые добавляют аргумент, например, new Circle(size, color, filled, ellipseProportions)где sizeи colorтребуется, а остальные по умолчанию.
Майкл К
15

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

Ищите параметры, которые можно сгруппировать, например (x и y, становятся точкой).

Являются ли эти дополнительные параметры флагами по умолчанию? Если вы используете флаги, функция должна быть разделена.

Это не означает, что у вас никогда не должно быть необязательных параметров, но, как правило, более одного или двух параметров указывают на запах кода.

Это также может указывать на то, что функция на самом деле должна быть классом с необязательными параметрами, измененными на свойства, и частью обязательных параметров конструктора.

CaffGeek
источник
1
+1 за осторожность. Любой функцией, независимо от того, насколько хорошо, можно злоупотреблять.
Майкл К
3
Это отличный совет для создания сверхпрочного кода равиоли, где пользователям вашего API нужно использовать как минимум 6 классов и 15 функций, чтобы сделать даже самое простое.
Дсимча
1
@dsimcha, как ты это понял из того, что я написал? Вау. Пожалуйста, объясни? Это было бы также плохо, если бы у вас была «суперфункция», которую вы получаете, когда у вас есть много дополнительных параметров. Прочитайте о принципах разработки SOLID и написании тестируемого кода. Желательно с использованием TDD. Тогда вернитесь и попытайтесь объяснить мне, что сокращение параметров в функциях - это плохо.
CaffGeek
1
Тестируемый код - это хорошо, но также и чистый, пригодный для использования API, который не слишком детализирован и не многословен и не вводит классы в ситуации, когда функция является надлежащей абстракцией. Я верю в принцип единой ответственности с обязанностями, определенными на высоком уровне абстракции. Если обязанности определены на слишком низком уровне, отдельные единицы становятся слишком упрощенными, так что их взаимодействия слишком сложны.
Дсимча
1
@dsimcha, вы упускаете суть. Отдельные единицы должны оставаться отдельными единицами, а не объединяться в одну функцию. Это также не означает, что все они являются общедоступными функциями. Ваш API является воротами к коду, и должен быть чистым и лаконичным. Функция с несколькими необязательными параметрами не является ни чистой, ни краткой. Однако перегрузка одной функции логическими параметрами гораздо понятнее. Например, во многих API есть функции, где два параметра являются необязательными, но требуется один или другой. Что ясно в этом, когда оба помечены как необязательные?
CaffGeek
4

Дополнительные параметры просто отлично

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

Вот некоторые примеры:

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 обнаруживает, что различные основные значения отсутствуют, и заполняет их, используя определенные значения по умолчанию (subject, body, cc, bcc и т. Д.). API поддерживается в чистоте, но все же гибкий.

Примечание о слишком многих параметрах

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

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

является идеальным кандидатом для рефакторинга Introduce Parameter Object для создания

String myMethod(ParameterObject po) {}

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

}

Это, в свою очередь, может привести к улучшению дизайна на основе шаблона Factory с предоставленной спецификацией в качестве объекта параметра.

Гэри Роу
источник
1
Функции форматирования строк, такие как printf, являются исключением из правила, можно утверждать, что, хотя они используют неограниченный список необязательных параметров, это скорее похоже на то, что аргумент является массивом, чем необязательными параметрами, несмотря на то, как он реализован.
CaffGeek
@ Я поправил свой ответ, чтобы лучше различать необязательные параметры и когда они переходят в запах кода (как вы упомянули в своем ответе).
Гари Роу
@ Гэри Роу, слишком много необязательных параметров в большинстве случаев тоже плохо.
CaffGeek
@ Я согласен, но в большинстве языков нет способа указать ограничение на количество необязательных аргументов, так что это подход «все или ничего». Вы вынуждены оставить это на усмотрение вашего метода, и, очевидно, если ваш метод имеет дело с 500 переменными, то он, безусловно, нуждается в рефакторинге.
Гари Роу
@ Гэри Роу, что ты имеешь в виду "большинство языков не предоставляют способ указать ограничение на количество необязательных аргументов"? В большинстве языков вы помечаете их как таковые или не предоставляете их значения при вызове функции, но в заголовке функции все еще определены параметры. Конечно, в некоторых языках вы можете добавить столько параметров, сколько захотите, после того, как вы заполнили определенные, но я не думаю, что это те дополнительные параметры, о которых мы здесь говорим. (кроме исключения формата строки)
CaffGeek
2

Одна из проблем с параметрами по умолчанию в C # (я думаю void DoSomething (int x = 1)) заключается в том, что они являются константами. Это означает, что если вы измените значение по умолчанию, вам придется перекомпилировать любых потребителей этого вызова метода. Хотя это достаточно легко сделать, бывают случаи, когда это опасно.

По-та-пят
источник
1

Это зависит от того, что делает ваш код. Если есть разумные значения по умолчанию, тогда вы должны использовать необязательные параметры, но если нет разумных значений по умолчанию, то добавление необязательных параметров сделает ваш код более сложным. Во многих случаях необязательные параметры являются аккуратным способом обхода нулевых проверок и устранения логики ветвления. Javascript не имеет необязательных параметров, но есть способ эмулировать их с помощью || (логический или), и я использую его все время при выполнении связанных с базой данных вещей, потому что, если пользователь не предоставляет какое-либо значение, я подставляю свои собственные значения с помощью || что избавляет меня от необходимости писать целую кучу утверждений if then.

davidk01
источник
1

Необязательные параметры - отличный способ сделать простые вещи простыми и сложные вещи возможными одновременно. Если существует явное разумное значение по умолчанию, которое большинству пользователей захочется, по крайней мере в случаях быстрого и грязного использования, то им не нужно писать шаблон, чтобы вручную указывать его каждый раз, когда они вызывают вашу функцию. С другой стороны, если у людей может быть веская причина для того, чтобы захотеть изменить это, то это нужно разоблачить.

Использование класса - ИМХО ужасное решение, так как оно многословно, неэффективно и несовместимо с типичной ментальной моделью того, что делает класс. Функция - идеальная абстракция для глагола, то есть выполнение чего-либо и возвращение. Класс - это правильная абстракция для существительного, то есть того, что имеет состояние и может управляться несколькими способами. Если первая должна быть ментальной моделью пользователя API, не делайте ее классом.

dsimcha
источник
1

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

bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
                      [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Мартин Викман
источник
1

Необязательные параметры - это в основном другой способ перегрузки функции. Так что это в основном сводится к: «это перегрузка функции плохо»?

Питер Б
источник
1

Я изначально любил эту функцию в Python и использовал ее для «расширения» уже используемых методов. И это выглядело красиво и легко, но скоро вернулось; потому что когда я добавлял необязательный параметр, это модифицировало поведение существующего метода, на которое опирался старый клиент, и таким образом, который не был обнаружен существующими модульными тестами. По сути, это нарушает Открытый Закрытый Принцип; код открыт для расширения, но закрыт для модификации. Поэтому я считаю, что использовать эту функцию для изменения существующего кода не очень хорошая идея; но хорошо, если используется с самого начала

Алекс Пуннен
источник
0

Я думаю, что было бы лучше перегружать функцию другими сигнатурами (то есть параметрами), чем использовать необязательные параметры.

жёстко
источник
Почему? Я думаю, что будет чище, если вы сможете объединить несколько перегруженных методов в один метод, используя параметры по умолчанию, если все методы имеют одинаковую базовую функциональность
Amit Wadhwa
Вы можете так думать. Я не из тех, кто думает, что Microsoft делает все правильно, но если бы вы были точны, я бы никогда не увидел перегрузок при использовании .NET Framework, только одну огромную сигнатуру функции - как в старом VB6.
HardCode