Отвлеченно о входных-выходных аргументах

в 9:14, , рубрики: былое и думы, ненормальное программирование, ни о чем, почему бы и нет, Программирование

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

Отвлеченно о входных-выходных аргументах - 1

В следующий раз о входных аргументах я задумался, когда впервые столкнулся с необходимостью разбора параметров командной строки в С/C++. Ну, помните это классическое:

int main(int argc, char* argv[])

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

Следующий раз задуматься о входных/выходных аргументах пришлось при анализе promises:

get('story').then(fnSuccess1).then(fnSuccess2). ... .catch(fnError);

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

Дальше — больше. В JavaScript нет перегрузки функций, поэтому там никого не парит такой код:

function sayHi() {
  for (var i = 0; i < arguments.length; i++) {
    alert( "Привет, " + arguments[i] );
  }
}

sayHi("Винни", "Пятачок"); // 'Привет, Винни', 'Привет, Пятачок'

После долгого общения с Java mistress такой код выглядит, словно обкуренный хиппи-шестидесятник рядом с офицером спецназа на боевом задании — "У этой функции вообще нет аргументов? Ну и что, расслабься, чувак! Давай-ка я скручу тебе arguments… На вот, дерни, и сколько бы тебе там чего не передали — все увидишь".

Более того, в JavaScript'е я есть такая функция, как apply:

fun.apply(thisArg[, argsArray])

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

В моей PHP-практике был случай, когда в стороннем модуле при перегрузке базового метода поменяли местами два аргумента (восьмой и деятый, или даже девятый и десятый — не суть важно).

public function doGood($a, $b, $c, $d, $e, $f, $g, %h, $i, $j) {}

public function doGood($a, $b, $c, $d, $e, $f, $g, %h, $j, $i) {
    parent::doGood($a, $b, $c, $d, $e, $f, $g, %h, $i, $j);
}

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

func(opts)

или

Response resp = service.call(req);

Кстати, последняя конструкция у меня прочно ассоциируется с BDSM BPMS — был как-то интересный опыт привязки intalio к web-приложению. Каждый процесс состоял из отдельных операций, которые имплементировались web-сервисами по схеме "y = f(x)", где x и y сводились к XML-документам (иногда простым, иногда не очень), а "программирование процессов мышкой" к маппингу элементов игреков одних сервисов на элементы иксов других сервисов.

Возможно поэтому в своей текущей практике (PHP) я попытался свести некоторые группы функций к схеме "y = f(x)". В JavaScript это делается легко и приятно.

Было

function showWarning(width, height, title, contents) {
    var width = width || 200; // если не указана width, то width = 200
    var height = height || 100; // если нет height, то height = 100
    var title = title || "Предупреждение";
    var contents = contents || "Ничего серьезного.";
    //...
}

Стало:

function showWarning(opts) {
    var opts = opts || {}; // если отсутствуют входные параметры
    var width = opts.width || 200; // если не указана width, то width = 200
    var height = opts.height || 100; // если нет height, то height = 100
    var title = opts.title || "Предупреждение";
    var contents = opts.contents|| "Ничего серьезного.";
    //...
}

В PHP приходится платить разработкой структуры входных/выходных аргументов в отдельных классах. В основном получается муторно, но иногда — весело.

К чему я это все? А к тому, что сейчас я уже не думаю, что было бы хорошо возвращать множество параметров вместо одного "y", а задумываюсь над тем, в каких случаях было бы хорошо иметь на входе всего один "x".

Автор: flancer

Источник

Поделиться

* - обязательные к заполнению поля