четверг, 11 декабря 2008 г.

cl-routes

Начал работу над cl-routes (по ссылке можно не ходить, там ещё ничего интересного)
Routes tackles an interesting problem that comes up frequently in web development, how do you map a URL to your code? While there are many solutions to this problem, that range from using the URL paths as an object publishing hierarchy, to regular expression matching; Routes goes a slightly different way.
(взято отсюда)

Если совсем вкратце, то это (будет) Common Lisp реализация Rails routes system (с этой ссылкой постоянно какие-то проблемы), но поскольку в Ruby, и тем более в Rails, я соображаю чуть менее, чем ничего, то ориентируюсь на Python-реализацию этой идеи.

Правда, упомянутые реализации делают упор на использовании в рамках шаблонна MVC, который (как впрочем и вообще паттерны) я, мягко говоря, недолюбливаю, так что, никаких намёков на MVC в cl-routes не будет.

Основное предназначение cl-routes это имея набор шаблонов типа:
/forum/:chapter/:topic/:message
/forum/archives/:year/:month/:day
и т.д.
из переданного URL, например, /archives/2008/12/11 извлечь информацию о year (2008), month (12) и day (11), а также дополнительную информацию, указанную при регистрации шаблона (например, функцию обработчик, или ещё что).

Реализация routes мне не понравилась (а ведь первой мыслью было просто тупо портировать на CL). Во-первых, слишком много буков. Во-вторых, она основана на регулярных выражениях, что требует в худшем случае полной проверки всех шаблонов и в случае сервера приложений, на котором работает много-много мини-приложений может привести к заметным издержкам. Вообще, разбиением URL на части (например, с помощью puri) данная проблема тривиальным образом сводится к задаче унификации:
(UNIFY ("forum" ?year ?month ?day)
("forum" "2008" "12" "11"))
Это позволяет отказаться от использования регулярных выражений и заметно упростить решение. В голову сразу пришло применить cl-unification. Однако, использование этой библиотеки в авторском виде приводит к необходимости, как и в случае использования регулярных выражений, просматривать все зарегистрированные шаблоны в поисках нужного. Но ведь в большинстве случаев структура сайта образует дерево, а поиск в дереве должен быть гораздо быстрее. Эта дилемма останавливала меня от начала работы: с одной стороны очень хотелось применить унификацию, а с другой, не менее сильно хотелось вести поиск в дереве, а не в линейном списке. Наконец меня осенило: если нельзя сделать дерево из шаблонов, то ведь можно сделать шаблон в виде дерева! Правда, для этого необходимо добавить к cl-unification or-template, который бы давал возможность включать в один шаблон несколько различных вариантов. Например:
#T("forum" #T(or #T("archives" ?year ?mount ?day)
#T(?chapter ?topic ?message)))
Последовательное рекурсивное применение or-template даёт возможность построить дерево произвольной сложности. Кроме того, необходимо добавить ещё несколько других шаблонов, например, concat-template для унификации шаблонов содержащих что-нибудь типа ":{id1}_:{id2}.html".

В итоге я решился пропатчить необходимым образом cl-unification и попробовать уговорить автора принять эти изменения. Начал писать около 12 ночи и около 3 сильно раздражённый сделал перерыв на сон: что-то с этой библиотекой не так... Кроме того, проснувшись я обнаружил, что в некоторых случаях она просто неверно работает, по крайней мере, с точки зрения унификации. Это стало последней каплей, показавшей бесперспективность ориентации на cl-unification. Решил сделать свое решение. Ну не совсем своё. Взял код Питера Норвинга из AIMA, немного разбавил его парой светлых идей из cl-unification (кои там всё же есть) и включил это дело в cl-routes. Попутно обнаружил, что автор cl-unification также пытался "творчески" переработать код Питера Норвинга, но вот получилось у него не очень...

Вот, надеюсь, что первый релиз cl-routes выпущу ещё до Нового Года.

Комментариев нет:

Отправить комментарий