Продолжение всемирной паутины
Андрей СобчукJabberID: andreis@jabber.ru. ICQ UIN: 46466235.
В последнее время, всё большее внимание к себе привлекает идея использования продолжений (continuations) для построения веб-приложений.
Продолжение это, если говорить упрощённо, то, что будет выполнятся дальше. Продолжения содержат всю информацию, чтобы продолжить выполнения программы с определённой точки. Продолжения похожи на GOTO, так как обе концепции позволяют перепрыгнуть в любое место программы. Но продолжения, в отличие от GOTO, позволяют запрыгнуть только в участок программы с определённым состоянием, которое должно быть сохранено заранее. В то время, как GOTO позволяет запрыгнуть в участок программы с неинициализированными переменными. Люди, знакомые только с традиционными языками программирования, могут представить продолжения, как копию текущего состояния стека и адрес следующей инструкции.
Теперь представим, что любая функция, кроме обычных параметров принимает один дополнительный параметр - продолжение, к которому перейдёт управление после окончания работы функции. Таким образом из функций никогда не происходит возврата. Функции просто продолжают работу продолжений. Такой метод называется "стиль передачи продолжений" (CPS - continuation passing style).
Как можно применить продолжения при разработке веб-приложений? Представим, что в нашем веб-сервере есть функция послатьФормуСПродолжением("имяСтраницы.html"). Эта функция захватывает текущее продолжение и сохраняет его (например сериализует) в скрытой переменной на странице. После нажатия кнопки "Отправить" ("Submit") наше продолжение запускается на выполнение. Таким образом создаётся иллюзия линейного потока выполнения программы.
Это позволяет писать веб-приложения так же, как и "обычное" ("настольное") приложения. Например так:
//В броузере выводится html страница с 1м вопросом целое1 = спроситьЧисло1("Введите число"); //Выводится страница со вторым вопросом целое2 = спроситьЧисло2("Введите второе число"); //Выводим результат if (код1 < код2) { показатьОкно("Первое число меньше второго"); } else { показатьОкно("Второе число меньше первого или равно ему"); }
Более подробно это разжёвано в ряде дискуссий: 1), 2), 3).
Что даёт такой подход. Сразу же отмечу, что "продолжения для веба" практически бесполезны при создании контентных сайтов. Они подходят именно для веб-приложений.
Основной конечный эффект заключается в том в том, что при написании веб-приложения с применением продолжений, можно ни разу не задуматься о том, что такое "сессия", "GET метод", "POST метод".
Думаю, что первопроходцем в этой области (как и в некоторых других областях) является Пол Грэхем. На данный момент существует довольно много реализаций веб-серверов с продолжениями:
- Seaside - Безусловный лидер по имеющейся функциональности. Язык программирования - Smalltalk. Основная разработка ведётся на Squeak, есть порты на VisualWorks и Dolphin. Из его дополнительных возможностей: обратные вызовы, прерывание продолжений (что, например, на корню ликвидирует проблему с двойными постами), развитая компонентная модель (что позволяет без лишних телодвижений, например, усовершенствовать инструментарий разработчика), возможность откатывать состояние при переходе от продолжения к продолжению, что должно использоватся для сохранения состояния пользовательского интерфейса. На данный момент существует, как минимум два движка шаблонов для Seaside.
- Borges - порт Seaside2 на Ruby. Интересен тот факт, что, насколько я знаю, Seaside зарождался именно на Ruby (году эдак в 2000).
- UnCommon Web - работает на различных диалектах Common Lisp. За основу тоже взят Seaside. Разработка началась недавно.
- WDialog - используемый язык - O'Caml.
- Chris Double - разрабатывает фреймворк на SISC-Scheme (интерпретаторе Схемы на Java). Запускается как сервлет в Tomcat. Не поддерживает компонентность a-la Seaside (похоже эту фичу мало кто поддерживает).
- Apache Cocoon Flow. Для описания потока выполнения использует интерпретатор JavaScript, модифицированный для поддержки продолжений.
- RIFE - похоже позволяет задавать поток выполнения прямо на Java.
Несмотря на то, что разработка веб-серверов с продолжениями - еще не совсем созревшее направление, уже существует ряд мифов:
- Использование продолжений приводит к невозможности использовать, кнопки "Назад" и "Вперёд" в броузере. Похоже, что корни этого заблуждения растут из "Yahoo! Store" Поля Грехема. Это не только неверно, даже наоборот. Использование продолжений позволяет не волноваться за то, что при помощи кнопки "Назад" пользователь перейдёт в "неожиданный" участок программы. Это не такая маленькая проблема, как может показаться на первый взляд, потому что может привести к дырам в безопасности
- Использование продолжений несовместимо с REST, что делает невозможным сохранение закладок пользователем. Этот миф появился потому, что при использовании продолжений, в дополнение к сессии появляется еще один параметр - идентификатор потока выполнения. Который невозможно спрятать от пользователя в куки. Тем не менее есть возможность, при генерации динамических путей, добавить в путь информацию, используя которую, позже можно перейти к определённому состоянию. Для примера можно взять блог "Learning Seaside". Обратите внимание на пример постоянных ссылок.
- Использование продолжений несовместимо с поисковиками. Обоснование - использование динамических URI (путей). На самом деле, используя динамически создаваемый robots.txt можно подсунуть поисковику подоходящую для индексирования версию сайта.
- Используя продолжения трудно создать сайт расчитанный на большое количесвто поситителей Обоснование - в зависимости от реализации, каждое продолжение может занимать до сотен килобайт. В такой ситуации можно воспользоваться несколькими решениями. Во-первых, при нехватке памяти можно сохранять/восстанавливать продолжения во внешней памяти. Будь то файловая система или база данных. Во-вторых, фабрика серверов. При этом, можно либо обеспечить привязку сессий к серверам, либо даже создать возможность миграции продолжений между серверами.
Кстати, все новые разработки - Python, Ruby, Perl6 - поддерживают "продолжения" изначально, что позволяет предположить, что у "продолжений для веба" большое будущее.
Если вас интересует больше "практической" информации, вам
следует почитать блог
Avi Bryant. Если интересует "теории", то посмотрите
A Better Web
API,
Web Programming
with Continuations,
The
Influence of Browers on Evaluators or, Continuations to Program Web
Servers, Inverting
back the inversion of control or, Continuations versus page centric
programming,
Interacting
on the Web, Automatically
Restructuring Programs for the Web, Developing
Interactive Web Programs,
Programming the Web with High Level Programming Languages,