Читаемость вложения вызовов тяжелых функций?

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

// Totally unreadable:
auto linesIter = filter!"a.length > 0"(map!strip(File(filename).byLine())))


// Perfectly readable.  The only difference is formatting.
auto linesIter = filter!"a.length > 0"(
    map!strip(
         File(filename).byLine()
    )
);

// Readable, but unnecessarily verbose:
auto rawLines = File(filename).byLine();
auto stripped = map!strip(rawLines);
auto filtered = filter!"a.length > 0"(stripped);

Написание чего-то вроде первого примера в форме вложенной функции, ИМХО, эквивалентно выполнению следующего кода в более процедурном стиле:

for(i = 0; i < 10; i++) { for(j = 0; j < 10; j++) { if(x < 2) { z++; } else { y++; }}}

В обоих случаях реальная проблема заключается в плохом форматировании, а не в чрезмерной вложенности. Как бы вы оценили удобочитаемость/понятность версии с хорошо отформатированной вложенной функцией по сравнению с версией с временной переменной? Считаете ли вы, что тяжелая вложенность вызовов функций — это плохой стиль, даже если она отформатирована для максимальной удобочитаемости? Если да, то почему?


person Community    schedule 02.02.2010    source источник
comment
Просто из любопытства: что это за язык? Я не знаю D, но ключевое слово auto и лямбды, закодированные как строки, выглядят так. И если да, то это D1 или D2 (или оба разрешены)?   -  person Jörg W Mittag    schedule 02.02.2010
comment
@Jorg: Да, это D2. Конструкции фильтра и карты взяты из std.algorithm.   -  person dsimcha    schedule 02.02.2010


Ответы (5)


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

Я очень рад добавить дополнительную переменную, чтобы разбить длинную строку на отдельные шаги (ваш пример 3), но ключевым моментом для меня является то, можете ли вы разбить все правильно на настоящие шаги. . Одним из хороших индикаторов является то, можете ли вы найти хорошее имя переменной; если вы не можете, возможно, это не настоящий отдельный шаг, который нужно разделить.

В вашем примере 2 нет ничего плохого, но он намного длиннее, и я бы, конечно, разбил его. Вы поблагодарите себя, когда дело дойдет до отладки...

person Community    schedule 04.02.2010

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

С временными переменными я стараюсь их избегать. И единственная причина этого проста: я совершенно не в состоянии давать им хорошие имена. Я пробую, когда они абсолютно необходимы, и заканчиваю тем, что трачу 5-10 минут на размышления: «Какое подходящее название для бла-бла, которое делает cor blimey»? И почти всегда в конечном итоге отказываются и используют buffer, если это массив, или temp, если это скаляр и т. д.

Тем не менее, с вашей вложенной структурой функции представляют глаголы, а не продукты действия глагола, что вы получили бы с временными переменными. С временными переменными у вас есть возможность дать этому продукту имя. Но если это то, что лучше описывается самим глаголом и прямым дополнением (verb(directObject)), то вам следует пойти по этому пути.

person Community    schedule 07.03.2011

ИМХО, объекты и имена должны быть тщательно выбраны, чтобы вещи были читаемыми, когда вы выполняете кодирование в стиле функций, помещая все в одну строку, как в вашем первом примере. Если это совершенно нечитаемо, кто-то выбрал плохие имена. Ваша цель состоит в том, что если что-то выглядит не так, часто это означает наличие ошибки.

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

person Community    schedule 04.02.2010

Лично я считаю, что если нет штрафов за производительность, читабельность важнее. Хотя я ничего не знаю о синтаксисе Лиспа, похоже, ваши примеры делают такое же количество вызовов? Если это так, сделайте это читаемым способом. Но если вы вызываете тяжелую функцию (например, открываете файл и читаете снова и снова) несколько раз в цикле, вам следует избегать этого. Я надеюсь, что этот ответ будет полезен.

person Community    schedule 02.02.2010

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

person Community    schedule 04.02.2010
comment
Я бы сказал, что сложные выражения с большей вероятностью будут содержать ошибки, особенно если кто-то другой (или вы сами через 6 месяцев) проводит техническое обслуживание. - person beny23; 05.02.2010
comment
Я основывал свое утверждение на том, что узнал из функционального программирования. Философия функционального программирования заключается в том, что сохранение состояния и изменяемых переменных является источником ошибок; выражения и функции предпочтительны, потому что они являются декларативными. т.е. выражать то, что мы хотим сделать, не серией шагов, а одним выражением. - person Markus Johnsson; 05.02.2010
comment
Думаю, это личные предпочтения. Я бы сказал, что если что-то выглядит проще и читабельнее, то оно более удобно в сопровождении и содержит меньше ошибок. Иногда это одно выражение, иногда несколько строк кода с некоторыми переменными со значимыми именами. - person beny23; 17.02.2010