В веб-приложении PHP, над которым я работаю, я вижу функции, определенные двумя возможными способами.
Подход 1:
function myfunc($arg1, $arg2, $arg3)
Подход 2:
// where $array_params has the structure array('arg1'=>$val1, 'arg2'=>$val2, 'arg3'=>$val3) function myfunc($array_params)
Когда я должен использовать один подход над другим? Похоже, что если системные требования продолжают меняться, и поэтому количество аргументов для myfunc продолжает меняться, подход 1 может потребовать много обслуживания.
Если система меняется так часто, что использование индексированного массива является лучшим решением, я бы сказал, что это меньше всего беспокоит вас. 🙂
В общих функциях / методах не должно приниматься слишком много аргументов (максимум 5 плюс или минус 2), и я бы сказал, что вы должны придерживаться использования аргументов named (и в идеале типа намека ). (Индексированный массив аргументов действительно имеет смысл, если имеется большое количество дополнительных данных – хорошим примером является информация о конфигурации).
Как говорит @Pekka, передача массива аргументов также может быть болью для документирования, а потому для других людей / себя в «n» месяцев для поддержания.
Обновление-Ette …
Кстати, упомянутая книга Code Complete рассматривает такие вопросы довольно подробно – это отличный том, который я бы очень рекомендовал.
Использование массива params (суррогат для так называемых аргументов «на других языках») отлично – я люблю его использовать самостоятельно, но он имеет довольно большой недостаток: аргументы не документируются с использованием стандартных имен phpDoc таким образом и следовательно, ваша IDE не сможет дать вам подсказки при вводе имени функции или метода.
Я считаю, что использование необязательного массива аргументов полезно, когда я хочу переопределить набор значений по умолчанию в этой функции. Это может быть полезно при построении объекта с множеством различных параметров конфигурации или просто для немого контейнера. Это то, что я взял в основном из мира Ruby.
Например, если я хочу настроить контейнер для видео на моей веб-странице:
function buildVideoPlayer($file, $options = array()) { $defaults = array( 'showAds' => true, 'allowFullScreen' = true, 'showPlaybar' = true ); $config = array_merge($defaults, $options); if ($config['showAds']) { .. } } $this->buildVideoPlayer($url, array('showAds' => false));
Обратите внимание, что начальное значение $ options является пустым массивом, поэтому предоставление его вообще необязательно.
Кроме того, с помощью этого метода мы знаем, что $ options всегда будет массивом, и мы знаем, что эти ключи имеют значения по умолчанию, поэтому нам не нужно постоянно проверять is_array()
или isset()
при ссылке на аргумент.
при первом подходе вы вынуждаете пользователей вашей функции предоставлять все необходимые параметры. во-вторых, вы не можете быть уверены, что у вас есть все, что вам нужно. Я бы предпочел первый подход.
Есть плюсы и минусы по каждому пути.
Если это простая функция, которая вряд ли изменится и будет иметь только несколько аргументов, я бы указал их явно.
Если функция имеет большое количество аргументов или, вероятно, многое изменит в будущем, я передам массив аргументов с ключами и воспользуюсь этим. Это также становится полезным, если у вас есть функция, в которой вам нужно просто часто передавать некоторые аргументы.
Пример того, когда я бы выбрал массив над аргументами, например, был бы, если бы у меня была функция, которая создала поле формы. возможные аргументы, которые я могу пожелать:
и мне может потребоваться лишь несколько из них. например, если поле type = text, мне не нужны параметры. Мне может не всегда понадобиться класс или значение по умолчанию. Таким образом, легче передать несколько комбинаций аргументов, не имея сигнатуры функции с аргументами тонны и все время пропуская нуль. Кроме того, когда HTML 5 становится стандартным много лет спустя, я могу добавить дополнительные возможные аргументы, такие как включение или отключение автозаполнения.
Если параметры, которые вы передаете, могут быть сгруппированы логически, вы можете подумать об использовании объекта параметра ( Refactoring , Martin Fowler, p295), таким образом, если вам нужно добавить дополнительные параметры, вы можете просто добавить больше полей в класс параметров и он не нарушит существующие методы.
Я знаю, что это старый пост, но я хочу поделиться своим подходом. Если переменные логически связаны в типе, вы можете сгруппировать их в классе и передать им объект в функцию. например:
class user{ public $id; public $name; public $address; ... }
и звоните:
$user = new user(); $user->id = ... ... callFunctions($user);
Если требуется новый параметр, вы можете просто добавить его в класс, а подпись функции не нуждается в изменении.