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

Мозговой штурм

Давайте немного подумаем, что мы хотим получить.

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

Для примера, у нас есть JavaScript-приложение, отвечающее за онлайн-пекарню. Одно из интересных нам сообщений может быть таким: «Партия из 42 батонов готова к доставке».

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

Еще один момент — безопасность. На самом деле, немногие из нас заботятся о внутренней безопасности своих приложений в должной мере. Когда мы определяем структуру приложения, мы говорим себе, что мы достаточно умны для того, чтобы понимать что в нашем коде должно быть публичным, а что приватным.

Хорошо, но поможет ли это если вы решите определить что именно разрешено модулю выполнять в системе? К примеру, в моем приложении, ограничив доступ из модуля веб-чата к интерфейсу модуля администрирования, я смогу уменьшить шансы на успешное использование XSS уязвимостей, которые я не смог найти в виджете. Модули не должны иметь доступ ко всему. Вероятно, в вашей существующей архитектуре они могут использовать любые части системы, но уверены ли вы, что это действительно необходимо?

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

Архитектура, которую я предлагаю вам

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

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

Теория модулей

Вероятно, в каком-то виде вы уже используете модули в своей существующей архитектуре. Если это не так, то в этой главе я покажу вам, как они устроены.

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

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

Каждое нетривиальное приложение должно создаваться из модульных компонентов. Рассмотрим GMail: вы можете рассматривать модули, как независимые единицы функциональности, которые могут и должны существовать сами по себе; возьмём к примеру чат. Скорее всего он основан на своём отдельном модуле чата, но так как этот модуль скорее всего очень сложный, то он вероятно состоит из более мелких вспомогательных модулей. Например, один из таких модулей мог бы отвечать за использование смайликов и он же мог бы использоваться не только в чате, но также и в почте.

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

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

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

В JavaScript есть несколько способов реализации модулей, включая шаблон «Модуль» и Object Literal (литеральная запись объекта var obj = {};). Опытные разработчики должно быть уже знакомы с ними. Если это так, то вы можете пропустить следующую главу и перейти сразу к главе «Модули CommonJS».

Авторизация