Я использую подход, заложенный в модуле WWW::Page, уже несколько лет, постоянно изменяя его код. Не будет преувеличением утверждение, что на каждом сайте работают разные варианты модуля.
Однако, мне хочется несколько поменять идеологию, сократив на треть число файлов, которые необходимы для развертывания сайта.
Сейчас URI запрошенной страницы отображается на один из нескольких XML-файлов с описаниями страниц. Иными словами, некий диспатчер определяет тип страницы и смотрит его описание в соответствующем файле. В таких XML, в частности, подключается один из кастомных модулей, отвечающих за логику приложения, дана ссылка на файл с XSLT-преобразованиями и записаны вызовы функций (из кастомного модуля). Типичный пример подобного файла описания входит в поставку.
Со временем стало ясно, что такая структура, хотя и позволяет полную свободу, отнимает много времени при добавлении на сайт новых страниц (точнее, типов страниц). Дело даже не в том, что это отнимает время; дело в том, что каждая такая операция — типовая: обновить диспатчер, научив его разпознавать новые адреса, создать описание страницы в XML, создать файл с XSLT.После выхода Perl 5.10 в диспатчерах применяется конструкция given/when, и на каждый тип страниц обычно приходится одна строка:
given($uri) { when(m{^/?$}) {$path = 'index.xml'} when(m{^/api/(rate)/[^/]+/?$}) {$path = "api/$1.xml"} when(m{^/api/[^/]+/?$}) {$path = 'api/rates-all.xml'} when(m{^/(currency|list|cloud)/?$}) {$path = "$1.xml"} ...
Не слишком утомительно и вполне расширяемо. Однако задача такого распределителя — подготовить переменную $path, записав в нее имя соответствующего XML-файла с описанием страницы.
Сами по себе файлы кешируются, поэтому сильных опасений о скорости работы в этом месте не возникает. Напрягает другое — типичный XML-файл оказывается совсем небольшим по размеру и кроме упомянутых выше инструкций обычно содержит только заголоков.
Сейчас (на самом деле лет уже 10 как, еще до появления WWW::Page) я вижу такое развитие подхода. Вместо имен файлов диспатчер сразу будет возвращать объекты страниц соответствющих классов. Есть, например, страница «Новости», для нее возвращается MySite::Page::News.
given($uri) { when(/^news$/) {return new MySite::Page::News::List} when(/^news/(.*)$) {return new MySite::Page::News::Detail($1)}
Этот подход я опробую на сайте books.perl.org.