Концепции Sv относительно 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};
}
Передача параметров не массивом, а хешем
sub function
{
my($it, $parm) = @_;
my $action = $parm->{action};
my $data = $parm->{data};
}
Этим не надо запоминать порядок параметров, а также в месте вызова хорошо видно назначение параметров по их ключам.
Если не обойтись без глобальные переменных, то объединять их в package:
foreach( 0 .. $cfg::max_lines )
{
# из языкового файла распечатываем сообщение $_
print $lang::msg[$_]."\n";
}
Синглтоны с ленивой инициализацией:
# получим данные первых 10 юзеров
my @users = map{ Usr->get($_) }( 0 .. 9 );
Здесь у нас есть package Usr, у которого есть метод класса get. При первом вызове этот метод проверяет существует ли синглтон класса Usr. Если существует - еспользует его. В противном случае создает, при этом могут быть выполнены sql запросы/инициализации и т.д.
Таким образом, если за текущий сеанс не будет ни одного обращения к классу Usr, то и не будет выполнена его инициализация.
Не забывать про многопоточность - создание синглтона должно быть потокобезопасным.
Приемчики:
# если на входе мы ожидаем целое число, то лучше перестраховаться:
my $num = int $parm->{num};
# если вещественное:
my $cash = $parm->{cash} + 0;
Никаких блоков {} больше страницы по вертикали. Всегда есть возможность разбить на подпрограммы.
Максимально уменьшать вложенность блоков {}.
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;
}
}
}
}
Заменяем на:
{
$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;
}
Возможен вариант:
my $err = 1;
{
...
...
проверка or last;
...
...
проверка or last;
...
...
проверка or last;
$err = 0;
}
if( $err ) # обработка ошибки
if( $act eq 'start' )
{
use Digest::MD5;
....
}
Если вы думаете, что модуль Digest::MD5 загрузится только когда $act eq 'start', вы заблуждаетесь. Модуль будет загружаться всегда, где бы не находился его вызов, хоть в самом конце скрипта. Я делаю так:
if( $act eq 'start' )
{
eval "use Digest::MD5";
$@ && die $@;
....
}
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 - ...
}
заменяю на:
my $p = $very_long_param_name;
if( $p > 0 && $p < 10 && $p != $param1 )
{
$param1 = $p + ...
$param2 = $p - ...
}
Даже если код кажется очевидным необходимо проверить все ситуации.
Писать код с мыслью `в каждом месте может возникнуть ошибка` и обязательно писать обработчики ошибок. Даже если сейчас провайдер возвращает валидные коды ответов, завтра он перепишет скрипты и вы будете получать sql инъекции.
Если клиент может ввести некорректные данные - он их введет. Возможно, не я это сформулировал...
Моделировать ситуации для всех ошибок.
Не жалеть комментариев, избегая совсем очевидных. Указывать к чему может привести изменение кода и на что обратить внимание, если кому-то таки понадобиться его изменить. Хотелка: научиться хорошо комментировать на английском языке.
Никогда не вываливать техническую инфу клиентам. При падении выводить заглушку "ведутся ремонтные работы", при этом серилизовать все данные падения в файл/БД.
Не бояться сказать `этот код говно` и переписать его полностью. Не жалеть удалять куски, мол, `я же все это писал, тратил время...`.
Если необходимо переписать код, вызываемый из многих мест, то можно `рядом` написать лучший и постепенно в разных местах менять вызовы на лучший. В конце старый код удалить.
Копирование кода - первый сигнал к тому, чтобы из него сделать подпрограмму.
Важно чувствовать баланс: иногда проще сформировать несложный xml вручную, а иногда лучше подключить модуль чтоб учесть абсолютно все нюансы (фильтрацию спецсимволов, кодировки). Любой дополнительный модуль - потенциальные дополнительные проблемы и баги, но иногда лучше довериться чужому опыту, чем потратить кучу времени на написание велосипеда.
Делать лучше можно бесконечно, важно остановиться на `очень хорошо и без багов`.
При тестировании на боевом сервере имеем кучу бесплатных бетатестеров и возможность обосрать свой продукт, а часто и невозможность отката данных из-за банальной ошибки.