«Совершенный Ajax» — новый подход к построению web-приложений, при котором web-сервер не генерирует ни строчки HTML-кода и взаимодействует с внешним миром только посредством web-служб; а клиентский интерфейс реализуется только на основе клиентских HTML, CSS, JavaScript.
Статья состоит из двух частей. В первой части — более живой и провокационной я постараюсь заинтересовать проблемой, рассказать о технологии «Совершенный Ajax» и показать ее применение на примере нашего проекта «Система Интерактивного Тестирования Знаний “Синтез”» (который имеет ряд интересных особенностей, таких, как использование серверного JavaScript на платформе Mozilla Rhino, прототипно-ориентированная ORM и поддержка SPARQL — языка запросов к Semantic Web).
Вторая часть – более занудная будет содержать много технических деталей и выйдет в следующий раз.
По доброй традиции, награждаю плюсиками всех участников дискуссии, в том числе и конструктивных критиков, с чьим мнением я не согласен.
Попробуйте угадать: к какой архитектуре относятся web-приложения?
К клиент-серверной говорите? Я ожидал, что Вы так ответите :-)
Что ж, давайте разберемся. В клиент-серверной архитектуре выделяют:
Преимущества клиент-серверной архитектуры очевидны; мы их все знаем:
Но, относятся ли web-приложения к клиент-серверной архитектуре?
Действительно, в web-приложениях есть сервер, отвечающий за бизнес логику приложения.
Но! За реализацию интерфейса отвечает не клиент, а тоже сервер. На сервере происходит обработка клиентской формы. Сервер генерирует HTML-код пользовательского интерфейса.
Клиент, т.е. браузер лишь визуализирует уже готовый HTML-код интерфейса. Это, фактически, то же самое, что прицепить к серверу монитор и объявить этот монитор клиентом…
Вряд ли такой подход можно назвать полноценной клиент-серверной архитектурой. Он имеет много недостатков:
Впрочем, мы знаем в истории пример подобной архитектуры. В 70-годы были распространены мейнфреймы. Мейнфрейм — такой огромный железный сундук (сервер), к которому подключались рабочие станции (клиенты). Причем, рабочая станция представляла собой просто монитор с клавиатурой. И любые действия клиента на рабочей станции обрабатывалось на сервере, порой даже такие как обработка нажатия на клавишу и обрисовка экрана [2]. Ну, мы знаем, насколько популярны мейнфреймы сегодня…
Конечно, в современных web-приложениях часть интерфейсной логики реализуется на клиенте с помощью JavaScript.
Часть данных загружается с помощью Ajax и визуализируется именно на клиенте.
Но, тем не менее, многие действия связанные с пользовательским интерфейсом, по-прежнему, выполняются на сервере. Использование Ajax сейчас во многом даже усугубляет ситуацию, т.к. приводит к разбрасыванию реализации интерфейса между серверным и клиентским кодом.
Подход «Совершенный Ajax» построен на следующих принципах:
Опишу эту архитектуру на примере нашего проекта «Система Интерактивного Тестирования Знаний “Синтез”».
В концепции «Севершенный Ajax» сервер должен удовлетворять одному-единственному условию: не генерировать ни строчки HTML-кода и осуществлять связь с внешним миром посредством web-служб. Во всем остальном его реализация ничем не ограничена.
Здесь я опишу структуру сервера в нашем проекте, т.к. она имеет ряд интересных особенностей: использование серверного JavaScript на платформе Mozilla Rhino, прототипно-ориентированная ORM и возможность использования SPARQL — языка запросов к Semantic Web.
Однако, Ваша реализация сервера может быть совершенно иной и совсем не похожей на нашу.
Наше приложение может иметь сколько угодно интерфейсных реализаций, разработанных любыми производителями.
Однако, оно всегда имеет в комплекте «родной» web-интерфейс.
Здесь я опишу его структуру.
Интерфейсное ядро — объектно-ориентированная JavaScript-библиотека, управляющая всем клиентским web-интерфейсом:
На Хабре есть статьи со схожими идеями, например «Ajax-машина» и недавняя «Hivext: Платформа веб сервисов».
Статья состоит из двух частей. В первой части — более живой и провокационной я постараюсь заинтересовать проблемой, рассказать о технологии «Совершенный Ajax» и показать ее применение на примере нашего проекта «Система Интерактивного Тестирования Знаний “Синтез”» (который имеет ряд интересных особенностей, таких, как использование серверного JavaScript на платформе Mozilla Rhino, прототипно-ориентированная ORM и поддержка SPARQL — языка запросов к Semantic Web).
Вторая часть – более занудная будет содержать много технических деталей и выйдет в следующий раз.
По доброй традиции, награждаю плюсиками всех участников дискуссии, в том числе и конструктивных критиков, с чьим мнением я не согласен.
Попробуйте угадать: к какой архитектуре относятся web-приложения?
К клиент-серверной говорите? Я ожидал, что Вы так ответите :-)
Что ж, давайте разберемся. В клиент-серверной архитектуре выделяют:
- Сервер — отвечает за хранение данных и реализацию бизнес-логики приложения.
- Клиент — отвечает за взаимодействие с пользователем [1].
Преимущества клиент-серверной архитектуры очевидны; мы их все знаем:
- Бизнес-логика не смешивается с пользовательским интерфейсом.
- Можно реализовать несколько клиентов с разными пользовательскими интерфейсами: интерфейс командной строки, оконный Windows-интерфейс, Flash, web-интерфейс, мобильный интерфейс и т.д.
- Клиентский компьютер не требователен к ресурсам;
- И т.д.
Но, относятся ли web-приложения к клиент-серверной архитектуре?

Действительно, в web-приложениях есть сервер, отвечающий за бизнес логику приложения.
Но! За реализацию интерфейса отвечает не клиент, а тоже сервер. На сервере происходит обработка клиентской формы. Сервер генерирует HTML-код пользовательского интерфейса.

Замечание:
Здесь, правда, есть одна тонкость. Следует различать два понятия: web-приложения и систему «браузер — web-сервер». Web-приложения работают поверх браузера и web-сервера, так же как Java-приложения работают внутри JVM, приложения на .Net работают внутри .Net Framework, а протокол HTTP работает поверх TCP/IP.
Система «браузер — web-сервер» действительно имеет клиент-серверную архитектуру: web-сервер принимает и обрабатывает запросы, а браузер визуализирует результат.
Однако, здесь мы говорим не о системе «браузер — web-сервер», а о работающих внутри нее web-приложениях.
Вряд ли такой подход можно назвать полноценной клиент-серверной архитектурой. Он имеет много недостатков:
- Смешивание бизнес-логики и пользовательского интерфейса;
- Сложно реализовать несколько пользовательских интерфейсов;
- Сторонни программы не могут обращаться к серверу (если не написан специальный api);
- Большая часть нагрузки по обработке интерфейса ложится на сервер.
- И т.д.

Конечно, в современных web-приложениях часть интерфейсной логики реализуется на клиенте с помощью JavaScript.

Но, тем не менее, многие действия связанные с пользовательским интерфейсом, по-прежнему, выполняются на сервере. Использование Ajax сейчас во многом даже усугубляет ситуацию, т.к. приводит к разбрасыванию реализации интерфейса между серверным и клиентским кодом.
Так вот, я предлагаю подход «Совершенный Ajax», который призывает развить идею Ajax до логического конца и полностью отказаться от использования сервера для реализации пользовательского интерфейса web-приложений. |
Подход «Совершенный Ajax» построен на следующих принципах:
- Web-сервер:
- Реализует только бизнес-логику приложения и не генерирует ни строчки HTML-кода;
- Взаимодействует с клиентом посредством web-служб: принимает текстовые запросы и возвращает только данные;
- Реализует только бизнес-логику приложения и не генерирует ни строчки HTML-кода;
- Пользовательский web-интерфейс:
- Реализуется только на основе клиентских HTML, CSS, JavaScript.
- Взаимодействует с web-сервером посредством объектно-ориентированной библиотеки-обертки над web службами;
- Используется исключительно семантическая верстка.
Элементы управления (вкладки, меню, деревья) описываются высокоуровневыми HTML-конструкциями.
- Библиотека контролов придает HTML-конструкциям внешний вид и функциональность соответствующего элемента управления, просто навешивая нужные стили и обработчики событий, не меняя при этом HTML-код элемента.
- Реализуется только на основе клиентских HTML, CSS, JavaScript.
- Любой сторонний разработчик может реализовать свою версию пользовательского интерфейса, причем не только на HTML, но и на Flash, Windows, Mac и т.д.
«Совершенный Ajax» в нашем проекте
Опишу эту архитектуру на примере нашего проекта «Система Интерактивного Тестирования Знаний “Синтез”».
Сервер
В концепции «Севершенный Ajax» сервер должен удовлетворять одному-единственному условию: не генерировать ни строчки HTML-кода и осуществлять связь с внешним миром посредством web-служб. Во всем остальном его реализация ничем не ограничена.
Здесь я опишу структуру сервера в нашем проекте, т.к. она имеет ряд интересных особенностей: использование серверного JavaScript на платформе Mozilla Rhino, прототипно-ориентированная ORM и возможность использования SPARQL — языка запросов к Semantic Web.
Однако, Ваша реализация сервера может быть совершенно иной и совсем не похожей на нашу.
Архитектура сервера
- СУБД — хранит данные.
- Прототипное объектно-ориентированное ядро бизнес-логики — реализует объект- ную модель и функциональность приложения.
- ORM — связывает базу данных с прототипным ядром бизнес логики.
- Web-сервер — открывает функции программы для внешнего мира посредством web-служб.
СУБД

- Все данные хранятся в обычной реляционной базе данных.
- Причем, используется только «чистый» SQL, без надстроек конкретных СУБД: хранимых процедур и т.д. Это делает базу данных независимой от той или иной СУБД.
- Связь базы данных с объектным ядром бизнес-логики приложения осуществляется через прототипно-ориентированную ORM.
Объектное ядро бизнес-логики

- Вся объектная модель приложения и его бизнес-логика заключена в прототипно-ориентированном ядре.
- Ядро написано на серверном JavaScript, на базе платформы Mozilla Rhino.
- Несмотря на недооцененность многими разработчиками, JavaScript — удивительно мощный, гибкий и красивый язык, превосходящий в ряде случаев по гибкости и функциональным возможностям таких монстров, как Java или C#. И мы используем по максимуму его возможности, такие как прототипно-ориентированное ООП, объекты-как-хеши, функциональное программирование, замыкания и т.д.
- Также, прототипно-ориентированная парадигма JavaScript позволяет гораздо более гибко работать с базой данных через ORM.
- Mozilla Rhino компилирует JavaScript в байт-код JVM.
Благодаря этому, наш серверный JavaScript не становится «вещью в себе», а может использовать все обилие наработок мира Java.
- Вообще, серверный JavaScript на основе Mozilla Rhino — это отдельная большая тема, и я постараюсь написать ряд статей по этому вопросу.
Прототипно-ориентированная ORM

- ORM служит для связи реляционной БД с прототипным объектно-ориентированным ядром бизнес-логики.
- Она позволяет не просто связывать две модели, но и строить объектные запросы любой сложности. Например:
найди классы, ученики которых по тестам 10 самых молодых преподавателей имеют за осень средний балл больший, чем по весенним тестам 10 самых старших
.
- Использование ORM для прототипно-ориентированных языков — это мега круто!
Реляционная модель БД гораздо ближе к прототипной модели ООП, нежели к классовй. Поэтому, применение прототипного похода решает ряд проблем, присущих современным класс-ориентированным ORM (см., например, статью Теда Ньюарда «Вьетнам компьютерной науки»).
- Прототипная парадигма ORM позволяет удивительно гибко работать с данными.
Ведь, в отличие от классового подхода, где структура объекта жестко задана; при прототипном подходе объект может иметь произвольный набор полей, а также объединять внутри себя и наследовать любые другие объекты.
В частности, это дает возможность обращаться к БД на SPARQL — языке запросов Semantic Web.
- К сожалению, за такую гибкость приходится платить производительностью. Наша прототипная ORM пока существенно уступает по скорости работы обычным классовым ORM. Но мы работаем над этим.
- Прототипно-ориентированная ORM — также отдельная большая тема, и я постараюсь посвятить ей ряд статей.
Web-сервер

- Web-сервер выполняет только одну-единственную задачу — связывает ядро бизнес-логики с внешним миром посредством web-служб.
- При этом он не генерирует ни строчки HTML-кода.
- Web-службы не просто открывают доступ к ограниченному предопределенному набору функций, а полностью реализуют все возможности приложения.
Например, при наличии соответствующих прав, через web-службы можно осуществить объектный запрос неограниченной сложности и получить произвольную выборку объектов.
Клиент
Наше приложение может иметь сколько угодно интерфейсных реализаций, разработанных любыми производителями.
Однако, оно всегда имеет в комплекте «родной» web-интерфейс.
Здесь я опишу его структуру.
Архитектура клиента
- Интерфейсное ядро — объектно-ориентированная библиотека, реализующая всю клиентскую логику и управляющая интерфейсом клиента.
- Библиотека-обертка — объектно-ориентированная обертка над web-службами, осуществляющая связь клиентского интерфейса с сервером.
- Семантическая верстка — используется для описания элементов интерфейса (контролов) посредством обычных HTML-конструкций;
- Библиотека контролов — придает HTML-конструкциям внешний вид и функциональность соответствующего контрола.
Интерфейсное ядро

- Реализует интерфейсную логику приложения.
- Взаимодействует с объектной моделью приложения на web-сервере через библиотеку-обертку.
- Взаимодействует с элементами управления (контролами) посредством библиотеки контролов.
- Осуществляет встраивание клиентского интерфейса нашего программы в web-интерфейсы других приложений.
Это дает неограниченные возможности для создания мэшапов. В отличие от обычных мэшап-приложений, таких как GMaps, YouTube и т.д., которые позволяют встраивать только небольшую часть интефейса; в нашем приложении интерфейс может встраиваться полностью.
Например, благодаря этому, на стороннем сайте можно не только разместить модуль прохождения тестирования, но и модуль редактирования тестов, а также управления правами пользователей.
- Управляет стилями интерфейса.
Стили не только позволяют задавать оформление программы, но и полностью контролируют расположение и свойства интерфейсных элементов. Особенно это полезно, когда программа работает не самостоятельно, а, встроенна в другое приложение в виде мешапа.
- Управляет локализацией интерфейса.
Библиотека обертка

- Клиентская реализация (как родной web-интрфейс, так и интерфейсы сторонних производителей) взаимодействует с объектной моделью и бизнес-логикой на сервере посредством web-служб.
- Однако, работать с web-службами напрямую неудобно: это лишает нас объектного подхода и понижает упровень абстракции.
Поэтому, гораздо удобнее работать через объектно-ориентированную библиотеку-обертку над web-службами. Библиотека обертка позволяет прозрачно работать с серверной объектной моделью приложения.
Пример:
Нам надо получить объект Морковкин Вася и сделать его учеником 3 «А» класса.
Вместо низкоуровневой работы с web-службами, мы прозрачно работаем с объектной моделью приложения посредством библиотеки-оберткиSintez
.
//Получаем с сервера объект Морковкин Вася<br> var objStudent1 = Sintez.getStudent ("this.firstName = 'Вася' and this.secondName = 'Морковкин'");<br> //Получаем объект 3 "А" класс<br> var objClass1 = Sintez.getClass ("this.getClassNuber() = 3 and this.liter = 'А'");<br> //Делаем Васю учеником этого класса<br> objClass1.addStudent (objStudent1);<br>
А уже библиотека-обертка кодирует вызов методов объектов как команды web-служб, пакует объекты перед отправкой их на сервер и распаковывает после получения.
- Для того, чтобы свою версию интерфейса мог реализовать любой сторонний производитель на любой платформе, мы выпускаем библиотеки-обертки не только для web-интерфейса на JavaScript, но и для других распространенных технологий: .Net, Java, Delphi, Flash и др.
Если для какой-то платформы мы еще не выпустили библиотеку-обертку, сторонний разработчик может ее реализовать и самостоятельно по заданной спецификации.
- Кстати, если серверный язык программирования поддерживает интроспексию, библиотека обертка может генерироваться автоматически.
Для этого, программа на сервере должна исследовать собственную объектную модель, и на ее основе сгенерировать код библиотеки-обертки для основных языков программирования.
Пока мы пишем библиотеки-обертки вручную, но, думаю, скоро доберемся и до автоматической генерации.
Семантическая верстка

- Весь пользовательский интерфейс реализуется на основе чистых xHTML, CSS и JS.
Несмотря на сильную недооцененность разработчиками, xHTML/CSS/JS является очень мощной и гибкой технологией построения интерфейсов.
- Использование семантической верстки является высокоуровневым программированием; а несемантическая мешанина тегов – низкоуровневым.
И если при старом подходе, когда HTML-код генерировался сервером, мы, несмотря на все уродство, могли себе позволить низкоуровневый несемантический подход;
то при подходе «Совершенный Ajax» мы просто обязаны использовать высокоуровневую семантическую верстку!
- Элементы управления (деревья, меню, вкладки и т.д.) описываются обычными высокоуровневыми HTML-конструкциями.
Например, меню или дерево описывается как обычный список, а вкладки, как наборdiv
’ов.
- А уже библиотека контролов делает из этих HTML конструкций элементы управления.
Библиотека контролов

- Библиотека контролов придает HTML-конструкциям внешний вид и функциональность соответствующего элемента управления.
- При этом HTML-код элемента не меняется, а на него просто навешивая нужные стили и обработчики событий.
- Для превращения HTML-конструкции в элемент управления, надо просто вызвать соответствующий JS-объект библиотеки контролов.
Работа с контролом происходит через вызов методов объекта.
Поскольку контролы не меняют код своей HTML-конструкции, элемент управления может быть «на лету» превращен в другой элемент простой заменой JS и CSS-классов.
Пример:
Дерево описывается не мешаниной тегов, а единой высокоуровневой HTML-кострукцией: вложенным списком.
<ul id = "ulTree1"><br> <li><br> Элемент 1<br> <ul><br> <li><br> Элемент 1-1<br> </li><br> <li><br> Элемент 1-2<br> </li><br> </ul><br> </li><br> <li><br> <!--...--><br> </li><br> </ul><br>
Для придания списку внешего вида и функциональности дерева, создается JS-объектControls.Tree
. Работа с деревом происходит через вызовы методов объекта.
//Создаем дерево<br> var objTree1 = new Controls.Tree ($("ulTree1"));<br> //Выделяем все узлы дерева, вызывая метод selectAll () созданного объекта<br> objTree1.selectAll ();<br>
В любой момент мы можем превратить дерево в меню, просто создав объектControls.Menu
:
//Превращаем дерево в меню<br> var objMenu1 = new Controls.Menu ($("ulTree1"));<br>
- В скором времени я собираюсь опубликовать статью на эту тему: «HTML — самый недооцененный язык построения интерфейсов в мире (СНЯПИМ)».
Примечания
- ↑ Речь идет о клиент-серверных приложениях с конечным пользователем. В клиент-серверных приложениях вроде «клиент — сервер базы данных», пользовательский интерфейс, разумеется, отсутствует.
- ↑ Позже, у мейнфреймов появились так называемые «умные клиенты», которые обладали собственным процессором и памятью, а наиболее продвинутые могли даже проверить форму перед отпракой на сервер. Это очень напоминает нынешнюю робкую попытку передать часть интерфейсной логики web-приложения на клиент с помощью Ajax.
См. также
На Хабре есть статьи со схожими идеями, например «Ajax-машина» и недавняя «Hivext: Платформа веб сервисов».