[Перевод] Руководство по оформлению кода на Перле

imageКонечно, у каждого программиста есть свои собственные предпочтения в отношении форматирования, но есть некоторые общие принципы, следование которым делает ваши программы легко читаемыми, понимаемыми и поддерживаемыми.

Главная фишка заключается в том, что ваши программы всегда должны запускаться с флагом -w. При необходимости, вы можете целенаправленно отключить это действие для конкретных участков кода через прагмы no warnings или переменную $^W. Так же, вы должны всегда запускать программы с использованием use strict, либо же четко понимать, почему вы этого не делаете. Прагмы use sigtrap и use diagnostics так же могут быть полезными.

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

Отступы в 4 колонки.  Открывающая фигурная скобка, по возможности, на одной строке с ключевым словом, иначе выровнена с ним по вертикали.  Пробел перед открывающей фигурной скобкой в многострочном блоке.  Однострочный блок может быть размещен на одной строке, включая фигурные скобки.  Перед точкой с запятой пробелы не пишутся.  Точка с запятой опускается в «коротких» однострочных блоках.  Пробелы вокруг большинства операторов.  Пробелы вокруг «сложных» конструкций (внутри фигурных скобок).  Пустые строки между частями кода, выполняющими разные задачи.  Неприжимающиеся else.  Между именем функции и открывающей скобкой пробелы не пишутся.  Пробелы после каждой запятой.  Длинные строки ломаются после операторов (исключая and и or).  После последней закрывающей скобки в строке должен быть пробел.  Выравнивайте по вертикали похожие элементы.  Опускайте избыточную пунктуации, если от этого не страдает ясность. У Ларри есть обоснование для всех этих штук, но он не утверждает, что все рассуждают так же, как он.Вот несколько других, более существенных вопросов оформления, о которых следует подумать:

Если вы МОЖЕТЕ сделать что-то определенным образом, это не значит, что вы ДОЛЖНЫ делать именно так. Перл спроектирован так, чтобы дать вам несколько способов сделать одно и то же, постарайтесь выбрать из этих способов более наглядный. Например, это: open (FOO,$foo) || die «Can’t open $foo: $!»; лучше, чем это: die «Can’t open $foo: $!» unless open (FOO,$foo); потому, что второй вариант прячет основной смысл этого выражения в условии. С другой стороны, print «Starting analysis\n» if $verbose; лучше, чем $verbose && print «Starting analysis\n»; 

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

Опять же, то, что вы МОЖЕТЕ опустить скобки во многих местах, вовсе не означает, что это следует делать. Сравните:

return print reverse sort num values %array; 
 return print (reverse (sort num (values (%array)))); 
 Если сомневаетесь — ставьте скобки. At the very least it will let some poor schmuck bounce on the % key in vi (прим. пер. — не смог перевести, вроде это какая-то шутка про редактор vi).Даже если вы не сомневаетесь, подумайте о психическом равновесии человека, который будет поддерживать код после вас, и который, вероятно, поставит скобки в неправильном месте. 

Не делайте бессмысленных проходов по циклу сверху до низу, ведь Перл предоставляет оператор last, позволяющий выйти в середине. Просто сделайте небольшой «недоотступ», чтобы показать это более наглядно: LINE: 
 for (;;) {
 statements; 
 last LINE if $foo; 
 next LINE if /^#/; 
 statements; 
 }
 
 Не бойтесь использовать метки циклов — они там для удобства, а так же для прерывания многоуровневых циклов. Смотрите предыдущий пример.  Избегайте использования grep (), map () или `обратных кавычек` в пустом контексте, когда вы просто выбрасываете возвращаемые ими значения. Все эти функции возвращают значения, так что задействуйте их. Либо же используйте цикл foreach () или функцию system ().  Для переносимости, если используются какие-то функции, которые могут быть не реализованы на некоторых машинах, тестируйте эти конструкции в eval, чтобы увидеть возникающие ошибки. Если вы знаете, в какой версии или в каком патче реализована нужная функция, проверяйте $] ($PERL_VERSION в модуле English), чтобы увидеть, есть ли она там. Модуль Config так же позволяет выяснять значения, определенные программой Configure при установке Перла.  Выбирайте запоминающиеся идентификаторы. Если вы не можете вспомнить, что означает ваша напоминалка — у вас проблема.  Если короткие идентификаторы типа $gotit вполне приемлемы, то в длинных идентификаторах следует использовать подчеркивания для разделения слов. Обычно гораздо проще читать $var_names_like_this, чем $VarNamesLikeThis, особенно тем, для кого английский язык не родной.Названия пакетов имеют некоторые исключения из этого правила. Перл неофициально резервирует названия модулей в нижнем регистре для прагм, таких как integer или strict. Другие модули должны начинаться с большой буквы и использовать смешанный регистр, по возможности без подчеркиваний, из-за ограничений примитивных файловых систем, в которых названия файлов, представляющих модули, должны вписываться в несколько байт. 

Вы можете счесть полезным использование регистра для обозначения области видимости или назначения переменной. Например: $ALL_CAPS_HERE только константы (остерегайтесь конфликта со встроенными переменными Перла)
 $Some_Caps_Here глобальные и статические переменные 
$no_caps_here переменные, ограниченные областью видимости Названия функций и методов, похоже, лучше всего работают в нижнем регистре. Например, $obj→as_string ().Вы можете использовать ведущее подчеркивание для указания того, что эта переменная или функция не должны использоваться за пределами пакета, в котором они объявлены. 

Если у вас есть реально навороченное регулярное выражение, используйте модификатор /x и добавьте немного пробелов, чтобы выражение выглядело не так страшно. Не используйте слеш в качестве разделителя, если само регулярное выражение содержит слеши или обратные слеши.  Используйте новые операторы and и or чтобы избавиться от слишком большого количества скобок в списочных операторах, а так же для того, чтобы не усложнять чтение пунктуационными операторами вроде && и ||. Вызывайте ваши подпрограммы так же, как если бы они были функциями или списочными операторами, чтобы избавиться от лишних скобок и амперсандов.  Используйте here-документы вместо повторного написания print ().  Выравнивайте похожие элементы по вертикали, особенно в конструкциях, которые все равно слишком длинные, чтобы поместиться на одной строке. $IDX = $ST_MTIME; 
$IDX = $ST_ATIME if $opt_u; 
$IDX = $ST_CTIME if $opt_c; 
 $IDX = $ST_SIZE if $opt_s;



mkdir $tmpdir, 0700 or die «can’t mkdir $tmpdir: $!»; 
chdir ($tmpdir) or die «can’t chdir $tmpdir: $!»; 
mkdir 'tmp', 0777 or die «can’t mkdir $tmpdir/tmp: $!»; 
 Всегда проверяйте код возврата системных вызовов. Хорошее сообщение об ошибке должно отправляться в STDERR и включать указание на то, какая программа вызвала проблему, какой системный вызов и с какими аргументами был выполнен с ошибкой, а так же (ОЧЕНЬ ВАЖНО), должно содержать стандартное системное сообщение о том, что именно пошло не так. Вот простой, но исчерпывающий пример: opendir (D, $dir) or die «can’t opendir $dir: $!»; 
 
 Выравнивайте по вертикали транслируемые символы, когда это имеет смысл: tr [abc]
 [xyz]; 
 
 Подумайте о повторном использовании. Зачем тратить силу ума на разовый выхлоп, если можно сделать что-то, что будет работать снова и снова? Постарайтесь обобщить ваш код. Постарайтесь написать модуль или класс. Постарайтесь сделать работу вашего скрипта чище с помощью use strict и use warnings (или -w). Постарайтесь поделиться вашим кодом. Постарайтесь изменить ваш взгляд на мир. Постарайтесь… а, ладно.  Попробуйте документировать код и использовать формат Pod на постоянной основе. Тут есть несколько общих соглашений: Используйте C<> для названий функций, переменных и модулей (и вообще всего, что можно считать частью кода, типа дескрипторов файлов или специальных значений). Обратите внимание, что названия функций оказывается легче читать, если у них есть скобки после имени, вроде такого — function ().  Используйте B<> для названий команд, таких как cat или grep.  Используйте F<> или C<> для названий файлов. F<> должен быть единственным Pod-кодом для имен файлов, но большинство Pod-конвертеров отображают его курсивом, из-за чего пути в Unix и Windows, содержащие прямые и обратные слеши, могут выглядеть плохо читаемыми и использование C<> выглядит предпочтительнее. Будьте последовательными.  Будьте клёвыми. 

© Habrahabr.ru