Оформление кода

1. Лесенка в 4 пробела

Обязательна «лесенка» с отступом в 4 пробела (half-tab). При этом запрещается в редакторе изменять размер отображаемой табуляции, например выставлять отображение табуляции в 4 пробела. Код, созданный Вами при таких настройках, будет некорректно отображаться в других редакторах с другими настройками.

2. Пробелы после запятых

После запятых и точек с запятой (если, конечно, они не расположены в конце строки) ставятся пробелы. Перед запятой и точкой с запятой пробелы не ставятся:

@a = (1, 2, 3);
for (my $i = 0; $i < $count; $i++) {  }

3. Пробелы вокруг знаков операций

Любые операторы / знаки операций (перечисленных в perlop, например "=", "==", "=>", "<", ">", "&&", "||" и т.п.) обязательно отделяются пробелами с обоих сторон

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

$a = $b * $c + $d * $e;
$a = $b * $c  +  $d * $e;

4. Пробелы после ключевых слов

После любых ключевых слов языка perl, а также имён функций / методов, обязательно следует пробел. Исключение составляет случай, когда за именем функции/метода следует открывающая круглая скобка, за которой следует пробел.
Примеры:

@foo = grep !/^#/, @bar;
@foo = mygrep( qr/^F/, @bar );

5. Пробелы вокруг сложных индексных выражений

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

$a[1];
$a[ 1 + 2 + 2 + 4 * function( $a{ $b->{c} } ) ];

6. Пробелы внутри круглых скобок при вызове функций

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

do_something_simple('abc'); # В этом случае аргументы пробелами можно не отделять
do_something_comprehensive( $a[1], $b->{c}->{d}->[0]->doit(), 1, undef, 2 ); # Хорошо
do_something_comprehensive($a[1], $b->{c}->{d}->[0]->doit(), 1, undef, 2); # ПЛОХО!

7. Пробелы после знака комментария

После символа начала комментария («#»)перед текстом самого комментария ставится пробел:

# Комментарии начинаются С ЗАГЛАВНОЙ БУКВЫ!
# Вторая строка комментария

Исключение составляют fancy comments, где допускается сливать начальнуй символ решётки с последующими символами:

############# MY COMMENT ###############
#************** INIT *******************

8. «Опять пробелы???»

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

Не стоит полагаться на подсветку синтаксиса как на «костыль», скрывающий недостатки форматирования.

9. Выравнивайте комментарии точно так же, как и код

Левый край комментариев выравнивается точно так же, как и основной код, т.е. используется принцип "лесенки".

# Тили-тили
# Трали-вали
if ($cond) {
    # Это дело мне по силе,
    # Откажусь теперь едва ли.
}
else {
    # Это мы не проходили,
    # Это нам не задавали!
}

Ставить символы «решётки» вначале строки, если левая граница кода находится правее, не допускается.

# Тили-тили
# Трали-вали
if ($cond) {
# ТАК ДЕЛАТЬ НЕЛЬЗЯ!!!
}

10. Максимальная длина строк. Разбиение длинных строк.

Строки желательно не оставлять слишком длинными; условное ограничение — 80-100-120 символов в строке. При необходимости строка разбивается на несколько.
Примеры допустимого разбивания конструкций:

very_long_statement
    if condition;
if (
    very_long_condition_1
    && very_long_condition_2
) {
    statement;
}
if (
    ..
  &&
    ...
  ||
    ...
) {
    ...
}

11. Открывающая фигурная скобка на той же строке, что и ключевое слово

Старайтесь придерживаться компактного (K&R) стиля оформления циклов и блоков ветвления: открывающая фигурная скобка находится на той же строке, что и ключевое слово «for», «if», «else», «while» и т. п.

После открывающей фигурной скобки обязателен перевод строки. Т. е. содержимое блока начинается с новой строки. Из этого правила могут быть исключения, см. п. 14.

Закрывающая фигурная скобка блока, состоящего из нескольких строк, должна находиться на одной вертикали с ключевым словом начинающим конструкцию.
Примеры:

if ($condition) {
    statement1;
}
else {
    statement2;
}
for (my $i = 0; $i < $count; $i++) {
    statement;
}

12. else — на отдельной строке

Не ставьте ключевые слова else и elsif на той же строке, что и закрывающая фигурная скобка, заканчивающая предыдущий блок. Начинайте конструкцию else / elsif с новой строки!

if ($condition) {
    statement1;
}
else {
    statement2;
}

Обоснование см. в PBP стр. 24: «Don't cuddle an else».

13. Пробел перед открывающей фигурной скобкой

Перед открывающей фигурной скобкой в блочных конструкциях всегда ставится пробел:

for (@array) {
    statement;
}

14. Допускается компактное оформление блоков из одного оператора

Однострочные блоки, состоящие из единственного оператора, могут быть помещены в одну строку вместе с открывающими и закрывающими скобками:

for (@array) { $_ *= 2; }
Возможно, лучше в подобных случаях использовать постфиксную форму записи:
$_ *= 2 for (@array);

15. Ставьте точку с запятой после каждого оператора

В Perl символ «;» является всего лишь разделителем (а не терминатором) операторов. В результате синтаксис позволяет НЕ ставить точку с запятой после последнего оператора блока. Однако, ставьте точку с запятой всё равно, даже если у вас всего лишь один оператор в блоке.

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

push @a, $a
print @a # Ошибка! Пропущена ";"

16. Ставьте запятую после каждого значения в многострочном списке

Следуя этому правилу, Вы сможете избежать лишних ошибок при добавлении элементов в конец списка. Также Вам будет проще перегруппировывать элементы списков, не заботясь о расстановке запятых.

my @dwarves = (
    'Happy',
    'Sleepy',
    'Dopey',
    'Sneezy',
    'Grumpy',
    'Bashful',
    'Doc',
);

17. Избегайте лишней пунктуации

Избегайте излишней пунктуации. В особенности, лишних скобок при вызове функций, или при выделении условий.

Например, опускайте круглые скобки для задания аргументов встроенных функций и функций, имеющих прототип:

@foo = grep !/^#/, @bar;

или при написании условия в операторе if с постфиксной записью, а также в тернарных операторах:

print "Ok" if $ok1 && $ok2;

$message = $success ? "OK" : "NOT OK";

Только не забывайте о приоритетах операций.

Словом, стоит опустить лишние скобки там, где их отсутствие не идёт в разрез с удобочитаемостью.

18. Разбивайте код на абзацы, при необходимости снабжённые комментариями

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

sub addarray_internal {
    my ($var_name, $needs_quotemeta) = @_;

    # Запомнить оригинал...
    $raw .= $var_name;

    # Добавить экранирование спецсимволов, если необходимо...
    my $quotemeta = $needs_quotemeta ?  q{map {quotemeta $_} } : $EMPTY_STR;

    # Перевести элементы переменной в строку, соединяя их с помощью "|"...
    my $perl5pat = qq{(??{join q{|}, $quotemeta \@{$var_name}})};

    # Добавить отладочный код, если необходимо...
    my $type = $quotemeta ? 'literal' : 'pattern';
    debug_now("Adding $var_name (as $type)");
    add_debug_mesg("Trying $var_name (as $type)");
    return $perl5pat;
}

19. Выравнивайте сходные элементы кода по вертикали

Выравнивайте сходные элементы по вертикали, особенно если они достаточно короткие чтоб поместиться в одну строку:

my %wm_conts_map = (
    first_name  => 'iname',
    last_name   => 'fname',
    email       => 'email',
);

$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: $!";

Вернуться к списку