Концепции Sv относительно perl и не только.

В порядке уменьшения важности:

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

код perl
sub function
{
    my($it, $parm) = @_;
    if( ! ref $it )
    {
        my $err_msg  = get_err_msg();
        my $err_code = get_err_code();
        die "$err_msg ($err_code)";
    }
    # Проверим на вшивость юзера с id = 10
    $it->{usr} = 10;
    my $res = $it->go;
    my @res = split /,/, $res, 3;
    $it->{adm}{login} = $res[2]{login};
}
use strict;

Передача параметров не массивом, а хешем

код perl
sub function
{
    my($it, $parm) = @_;
    my $action = $parm->{action};
    my $data   = $parm->{data};
}

Этим не надо запоминать порядок параметров, а также в месте вызова хорошо видно назначение параметров по их ключам.

Если не обойтись без глобальные переменных, то объединять их в package:

код perl
foreach( 0 .. $cfg::max_lines )
{
    # из языкового файла распечатываем сообщение $_
    print $lang::msg[$_]."\n";
}

Синглтоны с ленивой инициализацией:

код perl
# получим данные первых 10 юзеров
my @users = map{ Usr->get($_) }( 0 .. 9 );

Здесь у нас есть package Usr, у которого есть метод класса get. При первом вызове этот метод проверяет существует ли синглтон класса Usr. Если существует - еспользует его. В противном случае создает, при этом могут быть выполнены sql запросы/инициализации и т.д.

Таким образом, если за текущий сеанс не будет ни одного обращения к классу Usr, то и не будет выполнена его инициализация.

Не забывать про многопоточность - создание синглтона должно быть потокобезопасным.

Приемчики:

код perl
# если на входе мы ожидаем целое число, то лучше перестраховаться:
my $num = int $parm->{num};

# если вещественное:
my $cash = $parm->{cash} + 0;

Никаких блоков {} больше страницы по вертикали. Всегда есть возможность разбить на подпрограммы.

Максимально уменьшать вложенность блоков {}.

код perl
if( $a > $b )
{
    $c = ger_usr( $a );
    if( defined $c )
    {
        $d = get_balance( $c );
        if( $d > 0 )
        {
            $d++;
            if( can_print() )
            {
                $msg = get_balance_msg($d);
                print $msg;
            }
        }
    }
}

Заменяем на:

код perl
{
  $a > $b or last;
  $c = ger_usr($a);
  defined $c or last
  $d = get_balance($c);
  $d > 0 or last;
  $d++;
  can_print() or last;
  $msg = get_balance_msg($d);
  print $msg;
}

Возможен вариант:

код perl
my $err = 1;
{
  ...
  ...
  проверка or last;
  ...
  ...
  проверка or last;
  ...
  ...
  проверка or last;
  $err = 0;
}
if( $err ) # обработка ошибки
код perl
if( $act eq 'start' )
{
    use Digest::MD5;
    ....
}

Если вы думаете, что модуль Digest::MD5 загрузится только когда $act eq 'start', вы заблуждаетесь. Модуль будет загружаться всегда, где бы не находился его вызов, хоть в самом конце скрипта. Я делаю так:

код perl
if( $act eq 'start' )
{
    eval "use Digest::MD5";
    $@ && die $@;
    ....
}
код perl
if( $very_long_param_name > 0 && $very_long_param_name < 10 && $very_long_param_name != $param1 )
{
    $param1 = $very_long_param_name + ...
    $param2 = $very_long_param_name - ...
}

заменяю на:

код perl
my $p = $very_long_param_name;
if(  $p > 0 && $p < 10 && $p != $param1 )
{
    $param1 = $p + ...
    $param2 = $p - ...
}

Даже если код кажется очевидным необходимо проверить все ситуации.

Писать код с мыслью `в каждом месте может возникнуть ошибка` и обязательно писать обработчики ошибок. Даже если сейчас провайдер возвращает валидные коды ответов, завтра он перепишет скрипты и вы будете получать sql инъекции.

Если клиент может ввести некорректные данные - он их введет. Возможно, не я это сформулировал...

Моделировать ситуации для всех ошибок.

Не жалеть комментариев, избегая совсем очевидных. Указывать к чему может привести изменение кода и на что обратить внимание, если кому-то таки понадобиться его изменить. Хотелка: научиться хорошо комментировать на английском языке.

Никогда не вываливать техническую инфу клиентам. При падении выводить заглушку "ведутся ремонтные работы", при этом серилизовать все данные падения в файл/БД.

Не бояться сказать `этот код говно` и переписать его полностью. Не жалеть удалять куски, мол, `я же все это писал, тратил время...`.

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

Копирование кода - первый сигнал к тому, чтобы из него сделать подпрограмму.

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

Делать лучше можно бесконечно, важно остановиться на `очень хорошо и без багов`.

При тестировании на боевом сервере имеем кучу бесплатных бетатестеров и возможность обосрать свой продукт, а часто и невозможность отката данных из-за банальной ошибки.