пятница, 25 сентября 2009 г.

Parrot: Request Tracker и Trac Tracker

Разработчики Parrot отказались от использования Request Tracker в пользу Trac Tracker. А на душе остался осадок: ведь первый написан на Perl, а второй на Python.

Как-то не очень выглядит ситуация, когда разработчика виртуальной машины, предназначенной в первую очередь для языка Perl, уходят с инструмента, написанного на Perl, тем более, что этот инструмент весьма не плох.

Но может в Trac есть нечто, о чем я не знаю?

пятница, 18 сентября 2009 г.

Списки

Иногда забываю о таких замечательных модулях как List::Util и List::MoreUtils.
Почему забываю? Потому, что маленькие полезные подпрограммы по работе со списками из этих модулей легко и быстро реализовать самому.

Но почему не не стоит забывать? Потому, что эти полезные подпрограммы написаны на C, что положительно сказывается на больших списках.


use strict;
use warnings;

use List::Util;

use Benchmark qw(cmpthese);

my $foo = [1 .. 10000];

use vars qw($a $b);

cmpthese(1000, {
'manual' => sub {
my $s = 0;
$s += $_ foreach @$foo;
},
'List::Util::sum' => sub {
List::Util::sum(@$foo);
},
'List::Util::reduce' => sub {
List::Util::reduce { $a + $b } @$foo;
},
});

__END__

Rate manual List::Util::reduce List::Util::sum
manual 153/s -- -11% -91%
List::Util::reduce 171/s 12% -- -90%
List::Util::sum 1662/s 987% 871% --

четверг, 10 сентября 2009 г.

Url, обработчики и диспетчера

Url и обработчики

Первоначально web сайты целиком состояли из статических HTML страниц. Затем появился CGI, и сайты стали обзаводиться формами отправки данных и прочими динамическими станицами. Постепенно процент динамических страниц все увеличивался и увеличивался. Но url вида http://www.server.com/cgi-bin/foo.cgi не индексировались поисковиками, а также страдала эстетика, поэтому динамические страницы стали маскировать под обычные html: http://www.server.com/foo.html.

В то же время шло усложнение CGI скриптов, и повторяющийся код стали выносить в общие модули. Но не весь такой код можно было вынести в модули, в скриптах оставался код простой инициализации. Проще иметь одну точку входа, в которой посредством диспетчера вызывались обработчики конкретных команд, url.

Кстати, одну точку входа имели изначально те, что прятал статику за динамикой при помощи назначения обработчиков в Apache, а не при помощи mod_rewrite. Для тех, кто не прятал динамику за статикой, единая точка входа приводила к не слишком красивым url: http://www.server.com/index.php?action=foo, хотя при помощи mod_rewrite этого можно избежать.

Далее в статье web сайты являются лишь частным случаем.

Обработчики и диспетчера

В perl есть несколько возможностей сообщить диспетчеру какой код необходимо выполнять для каждой конкретной команды (url).

Можно просто вручную прописать таблицу диспетчеризации. Но при создании нового обработчика, можно забыть его зарегистрировать в таблице диспетчеризации, поэтому желательно чтобы эта регистрации происходила автоматически.

Автоматизации можно добиться при помощи задания необходимого атрибута подпрограммам-обработчикам и определения подпрограммы MODIFY_CODE_ATTRIBUTES. Например, модуль с обработчиками может иметь следующий вид:

package Foo::C::Too;
use base qw(Foo::C);
sub foo : Handler(foo) { '...' }
sub too { '...' }
sub baz : Handler(abc) { '...' }

Где подпрограммы foo и baz являются обработчиками команд foo и abc или обработчиками url http://www.server.com/foo.html и http://www.server.com/abc.html, а подпрограмма too не является обработчиком.

Модуль Foo::C::Too унаследован от Foo::C, в котором определена MODIFY_CODE_ATTRIBUTES:

package Foo::C;
sub MODIFY_CODE_ATTRIBUTES {
my ($package, $sub, @attr) = @_;
foreach (@attr) {
if (m/^Handler\((.+)\)$/) {
# Регистрация в таблице диспетчеризации
# подпрограммы $sub для команды $1.
# ...
last;
}
}
return ();
}

При запуске ядро просматривает каталог Foo/C/ и загружает все модули Foo::C::*, а perl уже сам, вызывает Foo::C::MODIFY_CODE_ATTRIBUTES для каждой подпрограммы модуля, унаследованного от Foo::C.

Подробности работы с атрибутами смотрите в perldoc attributes.

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

no strict "refs";
foreach (keys %INC) {
if (m/(Foo\/C\/.+)\.pm$/) {
my $p = $1;
$p =~ s/\//::/g;
while (my ($key, $val) = each(%{*{"$p\::"}})) {
if ($key =~ m/^h_(.+)/ and my $sub = *$val{CODE}) {
# Регистрация в таблице диспетчеризации
# подпрограммы $sub для команды $1.
# ...
}
}
}
}

Соответственно в модуле Foo::C::Too, обработчиками являются h_foo и h_baz:

package Foo::C::Too;
sub h_foo { '...' }
sub too { '...' }
sub h_baz { '...' }

На практике вместо префикса "h_" лучше использовать набор префиксов, например: "u_" - пользовательские команды, "a_" - команды администраторов, "o_" - команды доступные всем.

Дополнительные свойства обработчиков можно помещать в our переменные с именами, идентичными именам подпрограмм-обработчиков.

Последний способ: имя обработчика соответствует имени модуля. Этот способ хорошо подходит тогда, когда обработчики являются не просто подпрограммами, а целыми классами. Обычно такие обработчики находятся глубоко в системе и запрятаны за каким-то простым обработчиком.

Как видим, каждый из перечисленных способов имеет свои особенности, и в зависимости от цели стоит использовать наиболее подходящий.

А если вы занимаетесь просто созданием сайтов, то посмотрите готовые фреймворки.

пятница, 4 сентября 2009 г.

О вреде программирования

Каждая профессия накладывает на человека свой специфический отпечаток. Нередко этот отпечаток имеет негативную составляющую.

Специальность программирование взращивает в человеке иллюзию легкого исправления будь чего.
Но в реальной жизни не так просто исправить что-то.

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

Реальный мир имеет дело с материальными вещами, а их нельзя перекомпилировать после исправления ошибки.

P.S.
Знание языка Perl лишь усугубляет ситуацию, так как Perl является чрезвычайно гибким языком программирования.