Как указано в заголовке, полезны ли необязательные параметры, такие как те, что используются в C #, или они являются помехой для обслуживания приложений, и их следует избегать, поскольку они могут усложнить понимание кода?
Как указано в заголовке, полезны ли необязательные параметры, такие как те, что используются в C #, или они являются помехой для обслуживания приложений, и их следует избегать, поскольку они могут усложнить понимание кода?
Ответы:
Дополнительные параметры, по моему опыту, были хорошей вещью. Я никогда не находил их запутанными (по крайней мере, не более запутанными, чем действительная функция), так как я всегда могу получить значения по умолчанию и знать, что вызывается.
Одно из них - когда мне нужно добавить другой параметр в функцию, которая уже используется в общем, или, по крайней мере, в общедоступном интерфейсе. Без них мне пришлось бы переделывать исходную функцию, чтобы вызвать функцию, у которой есть другой аргумент, и которая может стать очень старой, если я добавлю аргументы более одного раза.
new Circle(size, color, filled, ellipseProportions)
где size
и color
требуется, а остальные по умолчанию.
В общем, если вам часто нужно много / необязательных параметров, ваши функции делают слишком много, и их следует разбить. Вы, вероятно, нарушаете SRP (принцип единой ответственности).
Ищите параметры, которые можно сгруппировать, например (x и y, становятся точкой).
Являются ли эти дополнительные параметры флагами по умолчанию? Если вы используете флаги, функция должна быть разделена.
Это не означает, что у вас никогда не должно быть необязательных параметров, но, как правило, более одного или двух параметров указывают на запах кода.
Это также может указывать на то, что функция на самом деле должна быть классом с необязательными параметрами, измененными на свойства, и частью обязательных параметров конструктора.
Дополнительные параметры просто отлично
Как правило, это оправдание: а) вы знаете, что у вашего метода есть много возможных аргументов, но не хотите перегружать его из-за боязни кластеризовать свой 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 с предоставленной спецификацией в качестве объекта параметра.
Одна из проблем с параметрами по умолчанию в C # (я думаю void DoSomething (int x = 1)) заключается в том, что они являются константами. Это означает, что если вы измените значение по умолчанию, вам придется перекомпилировать любых потребителей этого вызова метода. Хотя это достаточно легко сделать, бывают случаи, когда это опасно.
Это зависит от того, что делает ваш код. Если есть разумные значения по умолчанию, тогда вы должны использовать необязательные параметры, но если нет разумных значений по умолчанию, то добавление необязательных параметров сделает ваш код более сложным. Во многих случаях необязательные параметры являются аккуратным способом обхода нулевых проверок и устранения логики ветвления. Javascript не имеет необязательных параметров, но есть способ эмулировать их с помощью || (логический или), и я использую его все время при выполнении связанных с базой данных вещей, потому что, если пользователь не предоставляет какое-либо значение, я подставляю свои собственные значения с помощью || что избавляет меня от необходимости писать целую кучу утверждений if then.
Необязательные параметры - отличный способ сделать простые вещи простыми и сложные вещи возможными одновременно. Если существует явное разумное значение по умолчанию, которое большинству пользователей захочется, по крайней мере в случаях быстрого и грязного использования, то им не нужно писать шаблон, чтобы вручную указывать его каждый раз, когда они вызывают вашу функцию. С другой стороны, если у людей может быть веская причина для того, чтобы захотеть изменить это, то это нужно разоблачить.
Использование класса - ИМХО ужасное решение, так как оно многословно, неэффективно и несовместимо с типичной ментальной моделью того, что делает класс. Функция - идеальная абстракция для глагола, то есть выполнение чего-либо и возвращение. Класс - это правильная абстракция для существительного, то есть того, что имеет состояние и может управляться несколькими способами. Если первая должна быть ментальной моделью пользователя API, не делайте ее классом.
Проблема с необязательными аргументами заключается в том, что люди склонны использовать все больше и больше (и больше) аргументов функции вместо того, чтобы извлекать соответствующий код в новую функцию. Это доведено до крайности в php . Например:
bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
[, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Я изначально любил эту функцию в Python и использовал ее для «расширения» уже используемых методов. И это выглядело красиво и легко, но скоро вернулось; потому что когда я добавлял необязательный параметр, это модифицировало поведение существующего метода, на которое опирался старый клиент, и таким образом, который не был обнаружен существующими модульными тестами. По сути, это нарушает Открытый Закрытый Принцип; код открыт для расширения, но закрыт для модификации. Поэтому я считаю, что использовать эту функцию для изменения существующего кода не очень хорошая идея; но хорошо, если используется с самого начала
Я думаю, что было бы лучше перегружать функцию другими сигнатурами (то есть параметрами), чем использовать необязательные параметры.