NAME/НАИМЕНОВАНИЕ
perlstyle - Стиль написания Perl-кода
ОПИСАНИЕ
Безусловно, у каждого программиста есть свои собственные предпочтения относительно форматирования кода. Однако существуют некоторые общие рекомендации, которые сделают ваши программы читабельными, понятными и их поддержка не составит особого труда.
Самое важное - всегда запускать программы с флагом -w. В случае необходимости для определённых участков кода этот режим можно явно отключить, используя no warnings
или переменную $^W
. Также следует всегда работать с use strict
, кроме случаев, когда вы точно знаете, почему эта прагма вам не подходит. Использование прагмы use sigtrap
и даже use diagnostics
может также оказаться полезным.
Есть только один пункт, который Ларри рекомендует строго выполнять, с целью сохранения эстетики форматирования кода - закрывающая фигурная скобка многострочного блока должна находиться на одной вертикали с ключевым словом, начинающим конструкцию. Кроме того, он имеет ряд других предпочтений, но не на настолько строгих:
4х символьный отступ.
Открывающая фигурная скобка находится на той же строке, что и ключевое слово (если это возможно), иначе на одной вертикали с ним.
Пробел перед открывающей фигурной скобкой многострочного блока.
Однострочный блок может быть записан в одну строку, включая фигурные скобки.
Нет пробелов перед точкой с запятой.
В коротких однострочных блоках точка с запятой опускается.
Пробелы вокруг большинства операторов.
Пробелы вокруг "сложных" подпрограмм (внутри скобок)
Пустые строки между частями кода, реализующие разную логику.
"Не обнимать" else-условия
Между именем функции и открывающей круглой скобкой нет пробелов.
Пробел после каждой запятой.
Разбивать длинные строки, оставляя на конце какой-либо оператор (кроме
and
иor
).Пробел после последней сбалансированной круглой скобки в текущей строке.
Выравнивать соответствующие элементы по вертикали.
Опускать излишнюю пунктуацию до тех пор, пока код остается читабельным.
У Ларри есть причины для каждого из этих пунктов, но он не имеет претензий, если вы думаете по-другому.
Вот еще о чем стоит подумать:
То, что вы МОЖЕТЕ сделать что-то определённым образом вовсе не означает, что вы ОБЯЗАНЫ это делать так. Perl спроектирован таким образом, чтобы дать вам возможность сделать любую вещь несколькими способами, и так, чтобы вы смогли выбрать наиболее читабельный вариант. Например:
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))));
Если сомневаетесь - используйте скобки. В крайнем случае, пусть какой-нибудь дроздик попрыгает на клавише % в редакторе vi.
Даже если вы не сомневаетесь, подумайте о нервах того, кто будет поддерживать код после вас и, возможно, будет расставлять скобки не в тех местах.
Не идите на поводу у глупостей, искажая выход из цикла в начале или в конце. В Perl есть оператор С<last>, так вы можете выйти из цикла в середине. Только "вытяните" его, чтобы выход стал заметным:
LINE: for (;;) { statements; last LINE if $foo; next LINE if /^#/; statements; }
Не бойтесь использовать метки для циклов -- они предназначены для увеличения читабельности так же, как и для того, чтобы совершать прерывания многоуровневого цикла, как в предыдущем примере.
Избегайте использование
grep()
(илиmap()
) или `обратные_кавычки` в void-контексте, т. к. вы пропустите значения, которые они возвращают. Все эти функции возвращают значения, так используйте их. В противном случае, используйте циклforeach()
или функциюsystem()
соответсвенно.Для переносимости, когда вы используете особенности, которые не могут быть реализованы на каждой машине, выполняйте конструкцию в блоке eval. Если вам известен номер версии или патча, в котором данная особенность была реализована, то используйте переменную
$]
($PERL_VERSION
из модуляEnglish
), чтобы убедиться, что она там есть. Для того, чтобы узнать значения, определенные программойconfigure
во время установки Perl, используйте модульConfig
.Выбирайте осмысленные названия для идентификаторов. Если вы не можете вспомнить, что обозначает данное название, у вас проблемы с выбором имен.
Короткие название для идентификаторов типа
$gotit
являются понятными. Для длинных названий в качестве разделителя слов используйте символ подчеркивания. Например,$var_names_like_this
легче прочитать, чем$VarNamesLikeThis
, особенно тем, для которых английский -- не родной язык. Так же это простое правило распространяется наVAR_NAMES_LIKE_THIS
.Название пакетов и модулей -- исключение из этого правила. Так сложилось, что в Perl названия в нижнем регистре используются для прагм (например,
integer
илиstrict
). Остальные названия модулей должны начинаться с прописной буквы и использовать смешанный регистр букв, возможно, без подчеркиваний из-за того, что названия модулей используются в качестве названий файлов, которые должны укладываться в несколько байт.Вы можете найти полезным использование регистра букв для отражения области видимости или природы переменной. Например:
$ALL_CAPS_HERE константа (возможен конфликт с зарезервированными переменными!) $Some_Caps_Here глобальная или статическая переменная пакета $no_caps_here переменная, определенная через my() или local()
Имена функций и методов лучше смотрятся в нижнем регистре. Например,
$obj->as_string()
.Вы можете использовать подчеркивание в начале имени для обозначения того, что переменная или функция не должна быть использована вне пакета, в котором она определена.
Если вы написали, действительно, сложное регулярное выражение, то используйте модификатор
/x
и расставьте пробелов в выражение, так будет лучше. Не используйте слешы в качестве разделителей, если ваше регулярное выражение содержит слешы (/) или бекслешы (\).Используйте новые
and
иor
операторы, чтобы избежать заключения в круглые скобки нескольких списковых операторов и уменьшить использование пунктуационных операторов типа&&
и||
. Вызывайте ваши подпрограммы так, как будто они были функциями или списковыми операторами, для избежания лишних амперсандов и скобок.Используйте встроенные документы ("here" documents) вместо неоднократных вызовов
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<>
.
Будьте последовательны.
Пишите красивый код и будьте счастливы.
ПЕРЕВОДЧИКИ
Николай Мишин
<mishin@cpan.org>
=item * Анатолий Шарифулин<sharifulin@gmail.com>
=item * Алексей Суриков (Language)<KSURi>
=item * Михаил Любимов (Language)<mikhail.lyubimov>
=item * Дмитрий Константинов (Language)<Dim_K>
=item * Евгений Баранов (Language)<Baranov>