Должны ли мои функции PHP принимать массив аргументов или я должен явно запрашивать аргументы? - PullRequest
37 голосов
/ 22 января 2010

В веб-приложении 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 может потребовать много обслуживания.

Ответы [ 7 ]

29 голосов
/ 22 января 2010

Если система меняется так часто, что использование индексированного массива - лучшее решение, я бы сказал, что это меньше всего вас беспокоит. : -)

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

Как говорит @Pekka, передача массива аргументов также может быть проблемой для документирования и, следовательно, для других людей / вас в течение n месяцев.

Update-Ette ...

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

17 голосов
/ 22 января 2010

Использование массива params (суррогат для того, что в других языках называется «именованными аргументами») - это здорово - мне нравится использовать его самому, но у него довольно большой недостаток: аргументы не документируются с использованием стандартной нотации phpDoc, которая и, следовательно, ваша IDE не сможет давать вам подсказки при вводе имени функции или метода.

12 голосов
/ 22 января 2010

Я считаю полезным использовать массив аргументов необязательный , когда я хочу переопределить набор значений по умолчанию в функции. Это может быть полезно при создании объекта, который имеет много различных параметров конфигурации или является просто тупым контейнером для информации. Это то, что я взял в основном из мира 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() при ссылке на аргумент.

4 голосов
/ 22 января 2010

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

3 голосов
/ 22 января 2010

Если передаваемые параметры можно логически сгруппировать, можно подумать об использовании объекта параметра ( Рефакторинг , Мартин Фаулер, стр. 295), поэтому, если вам нужно добавить больше параметров, вы можете просто добавьте больше полей в ваш класс параметров, и это не нарушит существующие методы.

3 голосов
/ 22 января 2010

Есть плюсы и минусы в каждом направлении.

  • Если это простая функция, которая вряд ли изменится и имеет только несколько аргументов, то я бы сформулировал их явно.

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

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

  • Тип
  • Значение
  • класс
  • ID
  • стиль
  • опции
  • is_required

и мне, возможно, нужно будет пропустить только несколько из них. например, если поле имеет тип = текст, мне не нужны опции. Мне не всегда нужен класс или значение по умолчанию. Таким образом, легче передать несколько комбинаций аргументов, не имея сигнатуры функции с тоннами аргументов и постоянно передавая ноль. Кроме того, когда через много лет HTML 5 станет стандартом, я, возможно, захочу добавить дополнительные возможные аргументы, такие как включение или выключение автозаполнения.

0 голосов
/ 26 апреля 2013

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

      class user{
           public $id;
           public $name;
           public $address;
           ...
      }

и звоните:

      $user = new user();
      $user->id = ...
      ...

      callFunctions($user);

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

...