Паттерны для масштабируемых JavaScript-приложений ч.7

Собираем все вместе

  • Модули содержат специфичные части функциональности вашего приложения. Они публикуют уведомления, информирующие приложение о том, что случилось что-то интересное. Это их главная забота. Как я поясню в FAQ, модули могут зависеть от различных вспомогательных методов для работы с DOM, но идеальным бы было отсутствие любых зависимостей от других компонентов системы. Модули не должны иметь отношение к тому:
    • какие объекты или модули подписаны на их сообщения,
    • где находятся эти объекты (на клиенте или на сервере),
    • какое количество объектов подписано на уведомления.

  • Фасад — абстракция ядра защищающая его от прямого контакта с модулями. Он подписывается на интересные сообщения от модулей, и говорит: «Отлично! Что случилось? Расскажи мне больше подробностей!». Так же фасад поддерживает безопасность модулей, проверяя, действительно ли модуль, отправивший сообщение, имеет необходимые права для того, чтобы его сообщение было соответствующим образом обработано ядром.

  • Медиатор (ядро приложения) выступает в роли управляющего публикациями событий и подписками на них. Он отвечает за управление запуском и остановку модулей по необходимости. Здесь используется частичная динамическая загрузка зависимостей, и гарантия того, что упавшие модули могут быть централизованно перезапущены в случае проблем.

Итог этой архитектуры в том, что модули, в большинстве случаев, практически не зависят от других компонентов приложения. Они могут быть легко тестируемы и легко поддерживаемы в рамках своего кода. Кроме того, благодаря низкому уровню связанности кода, такие модули можно легко скопировать на новую страницу для использования в другом проекте, не прилагая дополнительных усилий. Так же, эти модули могут быть загружены или удалены динамически в процессе работы приложения.

Развитие идеи медиатора: автоматическая регистрация событий

Как раньше упоминал Михаэль Махемофф, размышляя о больших и масштабируемых JavaScript-приложениях, весьма выгодно использовать в приложении больше динамических свойств языка. Вы можете прочитать об этом больше в его заметках на странице Google+, но я хочу подробнее остановиться на одной особенности — автоматической регистрации событий (AER).

AER решает проблему связывания подписчиков и издателей путем добавления паттерна, который автоматически вызывает нужные методы на основе соглашения об именовании. Для примера, если модуль публикует сообщение messageUpdate, произойдет автоматический вызов одноименного метода у всех модулей, которые такой имеют.

Использование этого паттерна подразумевает регистрацию всех компонентов, которые могут подписываться на события, регистрацию всех событий на которые можно подписаться и, наконец, для каждого метода подписки в вашем наборе компонентов должно быть событие. Это выглядит очень интересно по отношению к нашей архитектуре, но так же имеет ряд интересных проблем.

К примеру, при работе динамически, объекты должны регистрировать себя после создания. Если вас это заинтересовало — посмотрите пост Михаэля об AER, где он более подробно обсуждает как бороться с проблемами этого подхода.

Часто задаваемые вопросы

Возможно ли обойтись без использования фасада (песочницы)?

Хотя архитектура, которую я изложил здесь, использует фасад для обеспечения безопасности, вполне возможно достичь того же с помощью медиатора — сообщения могут обрабатываться непосредственно ядром без использования фасада. Такая упрощенная версия все равно будет обеспечивать необходимо низкий уровень связывания кода, но при выборе этого варианта, нужно понимать, насколько вам будет комфортно работать с модулями, которые взаимодействуют напрямую с ядром.

В статье говорилось о том, что модули не должны иметь любых зависимостей, касается ли это библиотек (к примеру, jQuery)

Я специально вынес вопрос о зависимостях от других модулей сюда. Когда некоторые разработчики выбирают подобную архитектуру, этот выбор подразумевает что они будут использовать определенные абстракции от DOM-библиотек. К примеру, вы можете использовать вспомогательную утилиту, которая будет возвращать нужные вам DOM-элементы используя jQuery (или dojo). Благодаря этому, модули все еще могут удобно работать с DOM, но уже будут это делать не напрямую, жестко используя конкретную библиотеку. Существует достаточно много способов, как сделать модули независимыми, но стоит понимать, что, в обсуждаемой нами архитектуре, идеальные модули не должны иметь зависимостей.

Вы заметите, что иногда при таком подходе становится гораздо легче взять законченный модуль из одного проекта и перенести его в другой проект с небольшими дополнительными усилиями. Должен сказать, я полностью согласен с тем, что порой намного лучше, когда модули, вместо определенной части своей функциональности, просто используют другие модули. Как бы то ни было, держите в голове то, что такие модули, в некоторых случаях, могут потребовать гораздо больше усилий для переноса в другой проект.

Я хочу сегодня же начать использовать эту архитектуру. Есть ли какой-то шаблон от которого я бы мог оттолкнуться?

Когда у меня будет немного свободного времени, я планирую написать для этой книги бесплатный шаблон проекта, но сейчас, наверное, лучший выбор — платное учебное пособие написанное Эндрю Бэджис — «Написание модульного JavaScript» (разоблачу себя: деньги от этой реферальной ссылки, как и любые другие, полученные от этой книги деньги уже инвестируются в обзор будущих материалов перед тем, как я порекомендую их другим). Пособие Эндрю включает в себя скринкаст и примеры кода. Оно охватывает большую часть идей, которые мы обсуждали в книге, но в нем, вместо названия «фасад» используется слово «песочница», как у Николаса Закаса. Так же, здесь есть обсуждение о том, что работа с DOM-библиотеками, в идеале, должна быть реализована посредством абстракции. Я говорил об этом в предыдущем вопросе. Тут Эндрю делает ставку на некоторые интересные шаблоны, обобщающие работу с селекторами DOM, таким образом, в крайнем случае, замена библиотеки может быть выполнена в несколько коротких строк. Я не говорю, что это лучший или самый правильный подход, но я поступаю именно так.

Могут ли модули взаимодействовать с ядром напрямую, если это необходимо? Как заметил раньше Николас Закас, технически, нет никаких причин, мешающих модулям напрямую обращаться к ядру. Это скорее относится к «лучшим практикам». Если вы намерены строго следовать этой архитектуре, то вы должны также следовать ее правилам. Либо следовать правилам более простой архитектуры, которая была описана в первом вопросе.

Благодарности

Спасибо Николасу Закасу за его оригинальную работу в объединении большого количества концепций существующих на сегодняшний день. Спасибо Андрэ Хэнссон за технический обзор книги и за отзывы, которые помогли сделать эту книгу лучше. Спасибо Ребекке Мюрфей, Джастину Майеру, Питеру Мишо, Полу Айришу и Алексу Секстону и всем, чьи материалы относятся к теме обсуждаемой в книге и являлись источником вдохновения как для меня так и для других.

Авторизация