Как передать переменные в функцию? С массивом или переменными? - PullRequest
1 голос
/ 14 ноября 2009

Когда я пытаюсь реорганизовать свои функции для новых нужд, я время от времени спотыкаюсь о важнейшем вопросе:

Должен ли я добавить другую переменную со значением по умолчанию? Или я должен использовать только один массив, где я могу добавить дополнительную переменную, не нарушая API?

Ответы [ 6 ]

1 голос
/ 14 ноября 2009

Как и многие вопросы в программировании, правильный ответ - «это зависит».

Чтобы взять Javascript / jQuery в качестве примера, одним хорошим правилом является то, будет ли параметр требоваться при каждом вызове функции или является необязательным. Например, самой основной функции jQuery требуется выражение, чтобы определить, на какой элемент (элементы) повлияет операция:

jQuery(expresssion)

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

С другой стороны, многие плагины jQuery требуют нескольких дополнительных параметров, которые могут быть необязательными. По соглашению, они передаются как параметры через массив 'options'. Как вы сказали, это обеспечивает хороший интерфейс, так как новые параметры могут быть добавлены без влияния на существующий API. Это также делает API чистым, так как пользователь может игнорировать те опции, которые не применимы.

В общем, когда задействованы несколько параметров, передача их в виде массива является хорошим соглашением, поскольку многие из них, безусловно, будут необязательными. Это помогло бы очистить многие WIN32 API, хотя работать с массивами в C / C ++ труднее, чем в Javascript.

1 голос
/ 14 ноября 2009

Если вам не нужно поддерживать гибкое количество переменных, я думаю, что лучше явно указать каждый параметр. В большинстве случаев вы можете добавить перегруженный метод с другой сигнатурой для поддержки дополнительного параметра, при этом поддерживая исходную сигнатуру метода. Если вы используете массив для передачи переменных, это просто делает его слишком запутанным для пользователей вашего API. Очевидно, что есть некоторые входные данные, которые поддаются массиву (список точек в многоугольнике, список идентификаторов учетных записей, над которыми вы хотите выполнить действие и т. Д.), Но если это не переменная, которую вы разумно ожидаете, что она будет массив или список, вы должны передать его в метод как отдельный параметр.

0 голосов
/ 29 декабря 2009

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

Вот важные шаги к катастрофе: 1. добавить один или два параметра со значениями по умолчанию 2. некоторые абоненты будут предоставлять его, а некоторые будут полагаться на значения по умолчанию. [прошло пол года] 3. добавить обязательный параметр (перед ними) 4. изменить всех вызывающих абонентов, чтобы принять требуемый параметр 5. получить телефонный звонок или другое событие, которое заставит вас забыть изменить один из экземпляров в части # 2 6. Теперь ваша программа отлично компилируется, но является недействительной.

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

Массив также не является правильным решением. Массив следует использовать в качестве соединения похожих объектов, над которыми выполняется единообразное действие. Как говорится здесь , если стоит рефакторинг, стоит рефакторинг сейчас.

0 голосов
/ 14 ноября 2009

В своей книге Code Complete Стив МакКоннелл утверждает, что функция никогда не должна иметь более 7 аргументов, а иногда даже столько. Он приводит убедительные аргументы - которые я не могу привести по памяти, увы.

Чистый код , совсем недавно, выступает еще меньше аргументов.

Так что, если количество вещей, которые нужно передать, действительно мало, они должны быть переданы в обволакивающей структуре. Если они однородны, массив. Если нет, то для этой цели следует построить достаточно легкий объект.

0 голосов
/ 14 ноября 2009

Есть несколько соображений, которые необходимо учитывать.

  • Где используется эта функция? - Только в коде, который вы создали? Одно место или сотни мест? Объем работы, который необходимо выполнить для поддержки существующего кода, важен. Не забудьте указать количество времени, которое потребуется для общения с другими программистами, которые в настоящее время могут использовать вашу функцию.
  • Насколько критичен новый параметр? - Хотите ли вы требовать его использования? Если оно имеет значение по умолчанию, будет ли это значение по умолчанию нарушать существующее использование функции какими-либо тонкими способами?
  • Простота понимания - Сколько параметров уже передано в функцию? Чем больше число, тем более запутанным и подверженным ошибкам оно будет. Code Complete рекомендует ограничить количество параметров до 7 или менее. Если вам нужно нечто большее, вы должны попытаться абстрагировать некоторые или все связанные параметры в один объект.
  • Другие особые соображения. Хотите оптимизировать свои усилия для каких-либо особых условий, таких как скорость или размер кода? Существуют ли какие-то особые соображения, которые необходимо учитывать для вашей среды исполнения? Имейте в виду свои цели для проекта и убедитесь, что вы не работаете против них, какой бы дизайн вы ни выбрали.
0 голосов
/ 14 ноября 2009

Зависит от используемого языка программирования.

Если у вас заурядный язык OO, вы должны использовать объект, который вы можете легко расширить, , если вы действительно беспокоитесь о согласованности API .

Если это не так важно, есть возможность изменить сигнатуру метода и перегружать метод дополнительными / другими параметрами.

Если ваш язык также не поддерживает и вы хотите, чтобы API был бинарно стабильным, используйте массив.

...