- •Введение
- •Несколько слов о книге
- •Глава 1. Каким должен бытъ Web-интерфейс
- •Действия пользователя при работе с приложением
- •Накладные расходы при работе в сети
- •Асинхронное взаимодействие
- •Независимый и переходный образы использования
- •Четыре основных принципа Ajax
- •Браузер имеет дело с приложением, а не с содержимым
- •Сервер доставляет данные, а не содержимое
- •Реальное кодирование требует порядка
- •Применение богатых клиентов Ajax
- •Системы, созданные с использованием Ajax
- •Google Maps
- •Альтернативные технологии
- •Macromedia Flash
- •Java Web Start
- •Резюме
- •Ресурсы
- •Основные элементы Ajax
- •JavaScript изучался не зря
- •Определение внешнего вида с помощью CSS
- •Селекторы CSS
- •Свойства стилей
- •Простой пример использования CSS
- •Обработка DOM с помощью JavaScript
- •Поиск узла DOM
- •Создание узла DOM
- •Добавление стилей к документу
- •Свойство innerHTML
- •Асинхронная загрузка с использованием XML
- •Элементы IFrame
- •Объекты XmlDocument и XMLHttpRequest
- •Использование фуниции обратного вызова для контроля запроса
- •Жизненный цикл процедуры поддержки запроса
- •Отличия Ajax от классических технологий
- •Резюме
- •Ресурсы
- •Порядок из хаоса
- •Образы разработки
- •Реструктуризация и Ajax
- •Во всем надо знать меру
- •Реструктуризация в действии
- •Варианты применения реструктуризации
- •Несоответствие браузеров: образы разработки Fagade и Adapter
- •Управление обработчиками событий: образ разработки Observer
- •Повторное использование обработчиков событий: образ разработки Command
- •Обеспечение единственной ссылки на ресурс: образ разработки Singleton
- •"Модель-представление-контроллер "
- •Серверная программа Ajax, созданная без применения образов разработки
- •Реструктуризация модели
- •Разделение содержимого и представления
- •Библиотеки независимых производителей
- •Библиотеки, обеспечивающие работу с различными браузерами
- •Компоненты и наборы компонентов
- •Элементы, располагаемые на стороне сервера
- •Резюме
- •Ресурсы
- •Применение архитектуры MVC к программам различных уровней
- •Применение архитектуры MVC к объектам, присутствующим в среде браузера
- •Представление в составе Ajax-приложения
- •Отделение логики от представления
- •Отделение представления от логики
- •Контроллер в составе Ajax-приложения
- •Классические JavaScript-обработчики
- •Модель обработки событий W3C
- •Реализация гибкой модели событий в JavaScript
- •Модель в составе Ajax-приложения
- •Использование JavaScript для моделирования предметной области
- •Взаимодействие с сервером
- •Генерация представления на основе модели
- •Отражение объектов JavaScript
- •Обработка массивов и объектов
- •Включение контроллера
- •Резюме
- •Ресурсы
- •Программы, выполняемые на сервере
- •Создание программ на стороне сервера
- •N-уровневые архитектуры
- •Управление моделью предметной области на стороне клиента и на стороне сервера
- •Принципы создания программ на сервере
- •Серверные программы, не соответствующие основным принципам разработки
- •Использование архитектуры Model!
- •Использование архитектуры на базе компонентов
- •Архитектуры, ориентированные на использование Web-служб
- •Частные решения: обмен данными
- •Взаимодействие, затрагивающее только клиентскую программу
- •Пример отображения информации о планетах
- •Взаимодействие, ориентированное на содержимое
- •Взаимодействие, ориентированное на сценарий
- •Передача данных серверу
- •Использование HTML-форм
- •Использование объекта XMLHttpRequest
- •Управление обновлением модели
- •Резюме
- •Ресурсы
- •Создание качественного приложения
- •Отклик программы
- •Надежность
- •Согласованность
- •Простота
- •Как получить результат
- •Предоставление сведений пользователю
- •Поддержка ответов на собственные запросы
- •Обработка обновлений, выполненных другими пользователями
- •Создание системы оповещения
- •Основные принципы оповещения
- •Реализация базовых средств оповещения
- •Отображение пиктограмм в строке состояния
- •Отображение подробных сообщений
- •Формирование готовой системы
- •Предоставление информации в запросах
- •Информация о новизне данных
- •Простой способ выделения данных
- •Выделение данных с использованием библиотеки Scriptaculous
- •Резюме
- •Ресурсы
- •JavaScript и защита браузера
- •Политика "сервера-источника"
- •Особенности выполнения сценариев в Ajax-приложении
- •Проблемы с поддоменами
- •Взаимодействие с удаленным сервером
- •Взаимодействие с Web-службами
- •Защита конфиденциальной информации
- •Вмешательство в процесс передачи данных
- •Организация защищенного НТТР-взаимодействия
- •Передача шифрованных данных в ходе обычного HTTP-взаимодействия
- •Управление доступом к потокам данных Ajax
- •Создание защищенных программ на уровне сервера
- •Ограничение доступа к данным из Web
- •Резюме
- •Ресурсы
- •Что такое производительность
- •Скорость выполнения JavaScript-программ
- •Определение времени выполнения приложения
- •Использование профилировщика Venkman
- •Оптимизация скорости выполнения Ajax-приложения
- •Использование памяти JavaScript-кодом
- •Борьба с утечкой памяти
- •Особенности управления памятью в приложениях Ajax
- •Разработка с учетом производительности
- •Простой пример управления памятью
- •Как уменьшить объем используемой памяти в 150 раз
- •Резюме
- •Ресурсы
- •Сценарий двойной комбинации
- •Недостатки клиентского решения
- •Недостатки клиентского решения
- •Архитектура клиента
- •Разработка взаимодействия клиент/сервер
- •Реализация сервера: VB.NET
- •Написание кода сервера
- •Представление результатов
- •Применение каскадных таблиц стилей
- •Дополнительные вопросы
- •Запросы при выборе нескольких элементов
- •Переход от двойного связного выбора к тройному
- •Реструктуризация
- •Новый и улучшенный объект netContentLoader
- •Создание компонента двойного списка
- •Резюме
- •Глава 10. Опережающий ввод
- •Изучаем опережающий ввод
- •Типичные элементы приложений опережающего ввода
- •Google Suggest
- •Ajax как средство опережающего ввода
- •Структура серверной части сценария: С#
- •Сервер и база данных
- •Тестирование серверного кода
- •Структура клиентской части сценария
- •HTML
- •JavaScript
- •Обращение к серверу
- •Дополнительные возможности
- •Реструктуризация
- •День 1: план разработки компонента TextSuggest
- •День 3: включаем Ajax
- •День 4: обработка событий
- •День 5: пользовательский интерфейс всплывающего окна с предлагаемыми вариантами
- •Итоги
- •Резюме
- •Эволюционирующий портал
- •Классический портал
- •Портал с богатым пользовательским интерфейсом
- •Создание портала с использованием Java
- •Таблица пользователя
- •Серверная часть кода регистрации: Java
- •Структура регистрации (клиентская часть)
- •Реализация окон DHTML
- •База данных окон портала
- •Серверный код окна портала
- •Добавление внешней библиотеки JavaScript
- •Возможность автоматического сохранения
- •Адаптация библиотеки
- •Автоматическая запись информации в базе данных
- •Реструктуризация
- •Определение конструктора
- •Адаптация библиотеки AjaxWindows.js
- •Задание команд портала
- •Выводы
- •Резюме
- •Понимание технологий поиска
- •Классический поиск
- •"Живой" поиск с использованием Ajax и XSLT
- •Возврат результатов клиенту
- •Код клиентской части сценария
- •Настройка клиента
- •Инициализация процесса
- •Код серверной части приложения: РНР
- •Создание XML-документа
- •Создание документа XSLT
- •Объединение документов XSL и XML
- •Совместимость с браузером Microsoft Internet Explorer
- •Совместимость с браузерами Mozilla
- •Последние штрихи
- •Применение каскадных таблиц стилей
- •Улучшение поиска
- •Поддержка браузерами Opera и Safari
- •Использовать ли XSLT
- •Решение проблемы закладок
- •Реструктуризация
- •Объект XSLTHelper
- •Компонент "живого" поиска
- •Выводы
- •Резюме
- •Считывание информации из внешнего мира
- •Поиск XML-лент
- •Изучение структуры RSS
- •Богатый пользовательский интерфейс
- •Чтение лент
- •HTML-структура без таблиц
- •Гибкое CSS-форматироеание
- •Глобальный уровень
- •Предварительная загрузка средствами Ajax
- •Богатый эффект перехода
- •Правила прозрачности, учитывающие индивидуальность браузеров
- •Реализация затухающего перехода
- •Интеграция таймеров JavaScript
- •Дополнительные возможности
- •Введение дополнительных лент
- •Интеграция функций пропуска и паузы
- •Как избежать ограничений проекта
- •Обход системы безопасности браузеров Mozilla
- •Изменение масштаба приложения
- •Реструктуризация
- •Модель приложения
- •Представление приложения
- •Контроллер приложения
- •Выводы
- •Резюме
- •Отладчики
- •Для чего нужен отладчик
- •Средство Safari DOM Inspector для Mac OS X
- •Ресурсы
- •JavaScript — это не Java
- •Формирование объектов
126 Часть I. Новый взгляд на Web-приложение
Рис. З.7. Отношение "многие ко многим", реализованное в базе данных.
Втаблице C o l o r s перечислены значения цвета для всех изделий,
врезультате исчезает необходимость хранить информацию о цвете
втаблице Garments
В-третьих, для генерации XML-данных непосредственно используется набор результатов, полученный после обработки запроса к базе. На первый взгляд, кажется, что такое решение обеспечивает высокую эффективность работы, но при этом возможны две проблемы. Соединение с базой остается открытым в течение всего времени генерации XML-данных. В данном случае в цикле while не производятся сложные расчеты и соединение не будет открыто слишком долго, но в общем случае такое решение может стать причиной напрасного расходования ресурсов. Кроме того, подобный подход применим, только если мы рассматриваем базу данных как "плоскую" структуру.
3.4.2. Реструктуризация модели
На данном этапе работы мы храним списки цвета и размеров чрезвычайно неэффективно — помещаем значения, разделенные запятыми, в поля таблицы Garments. Чтобы преобразовать данные в соответствии с реляционной моделью, мы должны создать отдельную таблицу для хранения всех доступных значений цвета и вспомогательную таблицу, которая связывала бы изделия с цветом. Подобное отношение называется "многие ко многим" и показано на рис. 3.7.
Предположим, например, что вам нужна охотничья шляпа и вы хотите выяснить, шляпы каких цветов есть в наличии. Для этого вы обращаетесь к ключу garment_id в таблице Garments_to_Colors. Эти записи дают возможность получить первичные ключи в таблице Colors, и по ним мы видим, что в наличии имеются охотничьи шляпы цвета shocking pink и blueberry, а шляп цвета battleship gray нет в наличии. Можно сформировать и обратный запрос и использовать таблицу Garments_to_Colors, чтобы выяснить, какие изделия имеют требуемый цвет.
Глава 3. Управление кодом Ajax |
127 |
Теперь структура данных стала более строгой, но для того, чтобы получить информацию, надо формировать сложные запросы. Вместо того чтобы формировать такие запросы вручную, было бы лучше, если бы изделие можно было рассматривать как объект, в составе которого присутствовали бы массивы, задающие варианты цвета и размеры.
Инструмент Object-Relational Mapping
Существуют средства, способные выполнить описанную задачу за нас. Для этой цели подходит набор инструментов ORM (Object-Relational Mapping), которые автоматически преобразуют данные, содержащиеся в базе, в объект, хранящийся в памяти компьютера. При этом разработчик избавлен от необходимости формировать низкоуровневые SQL-выражения. Программисты, использующие РНР, могут обратиться к PEAR DB_DataObject, EZPDO (Easy PHP Data Objects) или Metastorage. Разработчики, применяющие Java, ограничены в выборе. Им доступен лишь продукт Hibernate (теперь он перенесен и на платформу .NET). Инструменты ORM — обширная тема, рассматривать которую мы сейчас не будем.
Рассматривая наше приложение с точки зрения MVC, легко увидеть, что применение ORM дает интересный побочный эффект — с самого начала у нас в руках оказываются основы модели. Мы можем написать программу генерации XML-данных, которая будет взаимодействовать с объектом Garment, предоставив ORM самостоятельно выполнять все необходимые действия с базой. Мы больше не привязаны к API конкретной базы данных и не должны учитывать особенности ее работы. В листинге 3.7 показаны изменения кода, связанные с переходом к ORM.
В данном случае мы определяем бизнес-объекты (т.е. модель) на РНР, используя Pear: :DB_DataObject, в результате чего наши классы становятся расширением базового класса DB_DataObject. Различные ORM делают это по-разному, но в результате мы получаем набор объектов, к которым можем обращаться как к обычному коду, абстрагируясь от сложных SQL-выражений.
Листинг 3.7. Объектная модель для приложения
require_once "DB/DataObject.php";
class GarmentColor extends DB_DataObject { var $id;
var $garment_id; var $color_id;
}
class Color extends DB_DataObject { var $id;
var $name;
}
class Garment extends DB_DataObject { var $id;
var $title;
var $description; var $price;
var $colors;
128 Часть I. Новый взглядна Web-приложение
var $category; function getColors(){
if (!isset($this->colors)){ $linkObject=new GarmentColor(); $linkObject->garment_id = $this->id; $linkObject->find(); $colors=array();
while ($linkObject->fetch()){ $colorObject=new Color(),• $colorObject->id=$linkObject->color_id; $colorObject->find();
while ($colorObj ect->fetch()){ $colors[] = clone($colorObject);
}
}
}
return $colors;
}
}
Помимо основного объекта Garment, мы определяем объект Color и метод объекта Garment, предназначенный для получения всех доступных цветов. Размеры поддерживаются аналогичным способом. Поскольку библиотека непосредственно не поддерживает отношение "многие ко многим", нам надо определить объект для связующей таблицы и организовать перебор в методе getColors (). Несмотря на это модель выглядит завершенной и удобна для восприятия. Рассмотрим, как можно применить данную модель к нашему документу.
Использование обновленной модели
Мы сгенерировали модель на основе более совершенной структуры базы данных. Теперь нам надо использовать ее в нашем PHP-сценарии. В листинге 3.8 показан код страницы, использующей объекты на базе ORM.
Листинг 3.8. Страница, использующая ORM для взаимодействия с базой
<?php
header("Content-type: application/xml");
echo "<?xml version=\"l.0\" encoding=\"UTF-8\" ?>\n"; include "gannent_busines8_objects.inc"
$garment=new Garment; $garment->category = $_GET["cat"]; $number_of_rows = $garment->find(); echo "<garments>\n";
while ( $garment->fetch()) { printf("<garment id=\"%s\" title=\"%s\">\n"
. "<description>%s</descrJ^tion>\n<price>%s</price>\n", $garment->id,
$garment->title, $garment->description, $garment->price
);
Scolors»
Глава 3. Управление кодом Ajax 129
$garment->getColors(); if (count($colors)>0){ echo "<colors>\n";
for($i=0; $i<count($colors);$i++){ echo "<color>{$colors[$i]}</color>\n";
}
echo "</colors>\n";
}
echo "</garment>\n";
}
echo "</garments>\n"; ?>
Вместо того чтобы конструировать SQL-запросы, создается пустой объект Garment, который затем частично заполняется данными, представляющими собой критерии поиска. Поскольку модель включается из отдельного файла, мы можем повторно использовать ее для поиска. Средства представления XML также генерируются на основе модели. Наши последующие действия по реструктуризации направлены на разделение XML-данных и процесса их генерации.
3.4.3. Разделение содержимого и представления
Код представления пока еще не отделен от объекта. Причина в том, что формат XML связан с кодом, предназначенным для его анализа. Если мы работаем с несколькими страницами, будет полезно, если мы сможем изменить XML-формат в одном месте приложения, оставив другие фрагменты без изменений. В более сложном случае может понадобиться поддержка нескольких форматов, например, один для представления перечня товаров пользователю, а другой для управления самим магазином. Поэтому желательно определить каждый формат только один раз и обеспечить для них централизованное отображение.
Системы на базе шаблонов
Для решения данной задачи используется язык шаблонов. Система, поддерживающая шаблоны, получает текстовый документ, содержащий специальную разметку. Элементы разметки обозначают позиции реальных переменных. К языкам шаблонов можно отнести PHP, ASP и JSP, которые позволяют включать фрагменты кода в содержимое Web-страниц. Этим они принципиально отличаются от кодов, включающих содержимое, примерами которых являются Java-сервлеты или традиционные сценарии CGI. Несмотря на то что сценарии предоставляют достаточно мощные средства обработки запросов, используя их, очень трудно разделить бизнес-логику и представление.
Языки сценариев, ориентированные на конкретное применение, например PHP Smarty и Apache Velocity (система на базе Java; при переносе на платформу .NET она получила название N Velocity), предоставляют ограниченные возможности для создания кода. В ряде случаев поток управления
130 Часть I. Новый взгляд на Web-приложение
может содержать лишь ветвление (оператор if) и циклы (например, операто- |
|
ры for и while). В листинге 3.9 показан шаблон PHP Smarty для генерации |
I |
XML-данных. |
|
<?xml version="1.0" encoding="UTF-8" ?> |
|
<garments> |
|
{section name=garment loop=$garments} |
|
<garment id="{$garment.id}" title="{$garment.title}"> |
|
<description>{$garment.description}</description> |
|
<price>{$garment.price}</price> |
|
(if count($garment.getColors())>0} |
|
<colors> |
|
{section name=color loop=$garment.getColors()} |
|
<color>$color->name</color> |
|
{/section} |
|
</colors> |
|
{/if} |
|
</garment> |
|
{/section} |
|
</garments> |
_ |
Входной информацией для шаблона является переменная массива gar- |
|
ments, содержащего объекты Garment. Блыпая часть шаблона генерируется |
|
процессором, а разделы в фигурных скобках интерпретируются как инструк- |
|
ции. Они либо заменяются именами переменных, либо интерпретируются как |
|
выражения ветвления и циклов. Структура выходного XML-документа, вы- |
|
раженная в виде шаблона, воспринимается гораздо лучше, чем код, подобный |
|
тому, который был представлен в листинге 3.7. Теперь поговорим о том, как |
|
применить шаблон к нашему документу. |
|
Использование обновленного представления
Мы переместили определение XML-данных из основного документа в шаблон Smarty. В результате главная страница должна лишь установить процессор шаблона и передать необходимые данные. В листинге 3.10 отражены изменения, необходимые для этого.
Листинг 3.10. Использование Smarty для генерации XML-данных
<?php
header("Content-type: application/xml"); include "garment_business_objects.inc"; include "smarty.class.php";
$garment«new DataObjects_Garment; $garment->category = $_GET["cat"] ; $number_of_rows - $garment->find(); $smarty-new Smarty;
$3marty->assign('garments', $garments); $smarty->display('garments_xml.tpl'); ?>
Глава 3. Управление кодом Ajax 131
рис. 3.8. Архитектура MVC применима к Web-приложениям. Web-страница или сервлет действует как контроллер и обращается к модели для получения
данных. Затем эти данные передаются 1а йлу шаблона (представление), который генерирует содержимое, предназначенное для передачи клиентской программе. Заметьте, что в данной ситуации предусмотрено только чтение данных. При модификации модели поток событий несколько изменится, но роли составных частей приложения останутся прежними
Обычно действия с шаблонами насчитывают три этапа. Сначала мы создаем шаблон Smarty, затем заполняем его переменными. В данном случае переменная только одна, но мы можем использовать их столько, сколько нам надо. Например, если информация о пользователе хранится вместе с данными о сеансе, мы можем сформировать посредством шаблона персональное приветствие. После этого мы вызываем функцию display () и передаем ей имя файла шаблона.
Итак, нам удалось отделить представление от страницы с результатами поиска. Формат XML определяется только один раз, и мы можем организовать воспроизведение данных несколькими строками кода. Страница с результатами поиска теперь ориентирована на решение одной задачи и содержит только необходимую для этого информацию, а именно: параметры поиска и определение выходного формата. Если вы помните, мы хотели обеспечить возможность легко переходить к форматам, альтернативным XML. С помощью Smarty это достигается просто, мы лишь определяем дополнительный формат. Если мы хотим реализовать структуру, обеспечивающую минимум изменений, мы можем даже использовать шаблон внутри другого шаблона.
Если вы вспомните, в чем состоит архитектура "модель-представление- контроллер", то увидите, что наше приложение соответствует ей. Реализация приложения условно показана на рис. 3.8.
В нашем наборе объектов постоянное хранение модели в базе данных обеспечивается посредством ORM. Представлением служит шаблон, определяющий XML-формат. Контроллер — это страница "поиска по категории" и другие документы, которые мы создадим и которые будут объединять модель и представление.
Мы рассмотрели пример применения архитектуры "модель-представление- контроллер" к Web-приложению. Мы обсуждали серверные программы приложения Ajax, поддерживающего XML-документы, но нетрудно понять, как применить данную архитектуру к классическому Web-приложению, поддерживающему HTML-документы.
В зависимости от технологий, возможны вариации данного образа разработки, но общие принципы остаются теми же. Компоненты Enterprise Jav-