Читаемость вложенности вызова тяжелых функций? - PullRequest
5 голосов
/ 02 февраля 2010

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

// 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);

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

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

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

Ответы [ 5 ]

2 голосов
/ 07 марта 2011

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

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

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

2 голосов
/ 05 февраля 2010

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

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

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

1 голос
/ 05 февраля 2010

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

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

0 голосов
/ 04 февраля 2010

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

0 голосов
/ 02 февраля 2010

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

...