Конечные автоматы в JavaScript. Часть 3: Тестируем виджет (исходники)Источник: IBM developerWorks Россия
Многие годы специалисты, занимавшиеся разработкой и реализацией сложного поведения в программах, управляемых событиями, использовали в качестве организационного принципа конечные автоматы. А теперь программируемые Web -браузеры открыли новую управляемую событиями среду для нового поколения приложений. Поскольку приложения на основе браузера, завоевавшие популярность благодаря Ajax, становятся все сложнее, проектировщики и специалисты по реализации могут получить преимущества от использования предлагаемых конечными автоматами дисциплины и структуры обработки. В части 1 данной серии статей описывался виджет-подсказка для Web-страницы, который демонстрирует более совершенное поведение, чем встроенные реализации подсказок в распространенных Web-браузерах. Для реализации такого поведения необходимо, чтобы виджет FadingTooltip реагировал на множество различных событий. Иногда реакция на какое-либо событие должна зависеть от предыдущего события. Для проектирования такого поведения мы использовали шаблон конечного автомата. Результирующие представления в виде графа и таблицы состояний показывают действия, выполняемые виджетом в ответ на каждое из событий во всех возможных ситуациях. Мы также составили список переменных, которые виджет должен помнить в промежутках между событиями, чтобы выполнять соответствующие действия. В части 2 мы перевели наш проект в код JavaScript, причем в полной мере использовали преимущества, предлагаемые замыканиями функций и ассоциативными матрицами. Наша реализация учитывает особенности популярных браузеров, не жертвуя эффективностью или изяществом. Мы создали код для: перехвата событий курсора для моделей событий всех трех браузеров, запуска и отмены обоих типов таймеров и перехвата событий таймеров. Мы реализовали таблицу состояний как общий обработчик для всех событий, и функциональную матрицу для всех действий и переходов. Подсказка представляет собой полностью параметризованный элемент HTML Division, который перемещается, постепенно появляется и постепенно исчезает в ответ на события курсора и таймера в соответствии с таблицей состояний. В этой, заключительной, статье серии мы протестируем нашу реализацию в некоторых популярных браузерах. Нам придется сконструировать простую тестовую страницу, которая создает несколько виджетов FadingTooltip и выполняет их привязку к HTML-элементам. Для сравнения наша тестовая страница также демонстрирует несколько встроенных подсказок. Мы сразу же столкнемся с несколькими непредусмотренными условиями и увидим, как изящно адаптируется к ним наш проект. В конце статьи приводятся некоторые замечания по поводу производительности и идеи, которые можно использовать при разработке конечных автоматов для приложений на базе браузера. Выполнение приложений в браузерахВ идеале приложения следует тестировать во всех вероятных средах выполнения. Для приложений на JavaScript это довольно пугающая задача, если учесть количество доступных браузеров и используемых версий. Поскольку виджет FadingTooltip предназначен только для демонстрации возможностей данной технологии, и его использование где-либо еще, кроме этой серии статей, не предполагалось, он был протестирован только с текущими версиями четырех популярных браузеров:
Виджет тестировался с использованием упрощенных условий тестирования, описание которых приводится в следующем разделе. Любое приложение, предназначенное для использования в реальных условиях, должно пройти более комплексное тестирование. Упрощенная среда тестированияПротестировать нашу реализацию можно с помощью некоторого фрагмента программного кода, встроенного в HTML-код Web-страницы. Код должен создать объекты FadingTooltip с помощью конструктора и выполнить их привязку к HTML -элементам. Это несложно выполнить при помощи функции, определенной в заголовке (head) HTML Web-страницы, и использующей атрибуты Листинг 1. Код JavaScript для создания виджетов FadingTooltip
Аргументами для функции Затем нам понадобятся некоторые HTML-элементы с атрибутами Листинг 2. HTML-код для некоторых HTML-элементов
Наконец, нам нужен некоторый код для вызова функции Листинг 3. Код JavaScript для привязки виджетов FadingTooltip к HTML-элементам
Первая подсказка (для HTML-элемента, определенного как Mozilla Firefox - это самый новый и передовой из доступных браузеров, он более тесно связан с открытыми стандартами, чем другие браузеры, поэтому мы начнем именно с него. (Если вы используете Microsoft Internet Explorer, то, возможно, имеет смысл сначала прочитать следующие два раздела, о непредусмотренных ситуациях и ошибке постепенного появления/исчезновения подсказки, а затем вернуться к этому разделу.) Теперь перейдем к среде тестирования. Она включает несколько HTML-элементов с встроенными подсказками и описанные выше примеры FadingTooltip, поэтому вы можете сравнить их. Обратите внимание на более сложное поведение виджетов FadingTooltips. Они становятся видимыми, когда курсор оказывается над HTML-элементом, и исчезают, когда он смещается с HTML-элемента, причем это происходит не внезапно, а постепенно. Они следуют за курсором, а при возникновении событий клавиатуры не исчезают. Их внешний вид более законченный: FadingTooltips оформлены с помощью стиля, содержат элементы форматирования текста и могут включать изображения. Вам решать, действительно ли эти отличия являются улучшениями, и стоит ли тратить время и усилия на разработку собственных виджетов-подсказок. Если да, то нужно скопировать исходные файлы для реализации и среду тестирования на жесткий диск, чтобы можно было изменять параметры, стили или код (см. раздел Загрузка). Для этого вам не нужен собственный Web-сервер, просто используйте файл:://... URL для загрузки среды тестирования с внесенными изменениями в браузер. Если случаются непредусмотренные событияMicrosoft Internet Explorer, безусловно, используется чаще всего , поэтому нашу реализацию необходимо протестировать и с этим браузером, при этом проблемы не заставят себя долго ждать. Предупреждение , показанное на рисунке 1, появится сразу же после того, как курсор окажется над любым из HTML-элементов с подсказкой-виджетом FadingTooltip. Рисунок 1. Непредусмотренное событие " mousemove" в Internet Explorer Обратимся к таблице состояний из раздела Заполняем таблицу состояний Части 1, которая показана на рисунке 2. Вспомните, мы не предполагали наступления событий Рисунок 2.Первоначальная таблица состояний для виджета FadingTooltip Интуитивно мы понимаем, что событие К счастью, дисциплина обслуживания, связанная с применением шаблона конечного автомата, теперь позволяет с легкостью вносить подобные изменения. Подумайте, какое поведение виджета будет подходящим, если событие Листинг 4. Код JavaScript для обработки непредусмотренного события mousemove в состоянии Inactive
Продолжая тестирование виджета в Internet Explorer, мы вскоре столкнемся с еще одной аналогичной непредусмотренной ситуацией, показанной на рисунке 3. Рисунок 3. Непредусмотренное событие " mouseout" в Internet Explorer Как и в предыдущем случае, интуиция позволяет нам предположить, что события Листинг 5. Код JavaScript для обработки непредусмотренного события mouseout в состоянии Inactive
На проектном этапе мы не предполагали, что события Рисунок 4. Непредусмотренное событие " mousemove" в Firefox К счастью, уже сделанные нами изменения для состояния Inactive позволяют Internet Explorer корректно обрабатывать эту ситуацию, поэтому для исправления данного дефекта в проекте дополнительные изменения не нужны. Но, к сожалению, при продолжении тестирования виджета после внесения изменений обнаруживается, что в Internet Explorer возникает еще одна непредвиденная ситуация: непредусмотренное событие " mouseover" в состоянии Pause. Поскольку события Листинг 6. Код JavaScript для обработки непредусмотренного события только в Internet Explorer
Если браузер представляет собой одну из версий Internet Explorer, измените таблицу Если постепенно появляющиеся/исчезающие подсказки появляются/исчезают не постепенноК сожалению, после того как все эти предупреждения о непредусмотренных событиях были устранены внесением в проект виджета изменений, описанных в предыдущем разделе, дальнейшее тестирование виджета в Internet Explorer обнаруживает еще одну проблему. Подсказки, определенные с помощью виджета FadingTooltip появляются и исчезают внезапно, а не постепенно. Печально, но Internet Explorer не поддерживает предлагаемый CSS стандартный стиль Internet Explorer не поддерживает нестандартный стиль с именем Листинг 7. Дополнение к коду JavaScript для создания подсказки в Internet Explorer
Необходимо также соответствующее дополнение в методе
Может показаться,что Opera известна как браузер не такому широкому кругу пользователей, тем не менее, этот браузер высоко ценится в технических кругах. К сожалению, разработчики Opera довольно поздно включили в свой браузер поддержку стиля для непрозрачности, предлагаемого CSS, поэтому виджеты FadingTooltip будут появляться и исчезать внезапно, а не постепенно во всех версиях этого браузера вплоть до 9. В отличие от Internet Explorer, в предыдущих версиях Opera не существует альтернативного синтаксиса для описания прозрачности, поэтому единственное решение проблемы - это модернизация до текущей версии. Еще немного о производительностиТеперь, когда наш виджет FadingTooltip стабильно работает во всех популярных браузерах, самое время выяснить, насколько мы близки к основной цели обеспечения производительности - минимальному использованию ресурсов процессора. Самый простой способ узнать это в среде Windows - понаблюдать за вкладкой Performance (Производительность) Task Manager (Диспетчера задач) Windows в процессе выполнения анимации виджета. На большинстве рабочих станций обычно некоторое количество программ незаметно для пользователя выполняются в фоновом режиме, даже если пользователь не запустил ни одного приложения. Некоторые из этих программ помещают небольшие значки рядом с часами в системном лотке Windows; другие вообще внешне ничем себя не выдают. Однако вкладка Performance (Производительность) Диспетчера задач Windows отображает их активность, как показано на рисунке 5. Рисунок 5. Фоновая активность программ в Диспетчере задач Windows Перед запуском виджета FadingTooltip можно остановить фоновую деятельность части программ, чтобы она не мешала оценить данные об использовании процессора виджетом. Большинство программ, отображающих значки в системном лотке Windows, можно закрыть через их контекстное меню. Другие программы, выполняющиеся в фоновом режиме, можно закрыть через апплет Services (Службы) Панели управления Windows. На системе с процессором Intel Pentium-III с тактовой частотой 1,1 ГГц, находящейся в состоянии бездействия, использование ресурсов процессора виджетом FadingTooltip действительно должно быть пренебрежительно малым, как показано на рисунке 6. Рисунок 6. Активность анимации виджета в Диспетчере задач Windows Поскольку анимация виджета предъявляет такие низкие требования к ресурсам процессора, можно быть уверенным, что виджет будет работать без проблем и в том случае, если процессор интенсивно используется другими программами. Не забудьте внести сделанные изменения в проектную документациюТеперь, после завершения тестирования реализации, необходимо внести сделанные нами изменения проекта и реализации в документацию. Выявленные непредусмотренные события соответствуют пустым ячейкам в таблице состояний, поэтому нужно внести в такие ячейки (они голубого цвета) действия, которые мы предприняли для разрешения этой ситуации, как показано на рисунке 7. Рисунок 7. Таблица состояний для виджета FadingTooltip по итогам тестирования Как показано на рисунке 8, ничуть не сложнее внести изменения в граф состояний Рисунок 8. Граф состояний для виджета FadingTooltip по итогам тестирования Строки, которые мы вставили в методы Дальнейшая разработкаЦель этой серии статей - продемонстрировать применение шаблона проекта конечного автомата к приложениям на базе браузера и использование двух характерных особенностей языка JavaScript в процессе создания красивой и эффективной программы. В результате мы разработали виджет FadingTooltip в виде отдельного самодостаточного объекта JavaScript. Код получился легким, но не особенно гибким. В завершение я хочу указать некоторые возможные направления для дальнейших разработок. Другие визуальные виджеты могут выиграть, если будут иметь внешний вид и поведение, аналогичные виджету FadingTooltip. Например, можно разработать сообщение о синтаксической ошибке при ошибке набора в поле ввода, рекомендации по заполнению сложных форм или рекомендации по работе в незнакомом рабочем окне в виде окон, оформленных при помощи стиля, аналогичные подсказкам, которые появляются в поле зрения под диктовку некоторого события, перемещаются вслед за курсором, и, соответственно, исчезают из поля зрения, когда этого требуют события. Одно из возможных направлений следующего этапа разработки может заключаться в переделке кода виджета FadingTooltip, а именно в выделении основного механизма конечного автомата в отдельный объект. Этот объект может включать перехват событий, обработчик событий, методы обработки ошибок и таймеров. Далее, можно создать семейство визуальных виджетов, в том числе, виджет FadingTooltip как отдельный объект, наследующий данные и методы от базового объекта с добавлением переменных состояний, таблиц переходов и методов действий, необходимые для каждого типа виджета. Виджеты, аналогичные подсказкам, и другие визуальные виджеты могут выиграть от применения дополнительных анимационных эффектов наподобие постепенного появления/исчезновения. Например, подсказки могут "соскальзывать" в поле зрения от края окна, увеличиваться, как бы вырастая из точки схода, появляться в поле зрения, раскладываясь из значка наподобие оригами, или трястись, как желе, когда курсор перемещается вслед за ними. Любой из этих анимационных эффектов может быть таким же эффектным с контекстными меню, диалоговыми окнами и приглашениями к вводу информации, как с виджетами-подсказками. Возможно и другое направление дальнейшей разработки - создание инфраструктуры для визуальных виджетов, которая будет способствовать выделению конечных автоматов для каждого вида анимации и поведения для каждого типа объектов в отдельные объекты, чтобы любую их комбинацию можно было привязать к конкретному HTML-элементу. Конечно, в этой статье мы не смогли рассмотреть несколько других типов событий, например, события, инициируемые клавиатурой или сетевыми запросами. В частности, при вводе отдельных символов в текстовое поле ввода могли бы запускаться действия проверки корректности вводимых значений по мере ввода и отображения оставшихся корректных значений в форме списка выбора на основе формальной грамматики, представленной в виде конечного автомата. Некорректные или просроченные сетевые запросы могли бы обрабатываться посредством повторных запросов к альтернативным сервисам, представленным как графы протоколов. Могут быть и другие возможные этапы дальнейшей разработки:
Другие программы, выполняющиеся под управлением того же процессора, могут являться источниками событий и производить действия, которые могут использовать программы, выполняющиеся в браузерах. Например, приложение для общения голосом посредством-IP-телефонии может генерировать события |