Привет!

Масштабируемый js для корпоративных сайтов

Гадашевич АндрейГадашевич Андрей

Как мы поменяли подход к архитектуре js в разрабатываемых нами сайтах. Модули, масштабируемость, ориентация на поддержку и развитие проектов.

Разрабатываемые нами сайты становятся все сложнее и сложнее, веб-интерфейсы уже больше похожи на полноценные приложения со сложными взаимодействиями, нежели на простые странички и навигацию между ними. Эти факторы заставили нас задуматься над архитектурой нашего js кода, так как именно java script отвечает за динамику и взаимодействие пользователя с интерфейсом.

Как мы делали

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

Почему это перестало подходить нам

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

@font-face { 
font-family: 'DroidSerifRegular';
src: url('../fonts/DroidSerif-Regular-webfont.eot');
src: url('../fonts/DroidSerif-Regular-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/DroidSerif-Regular-webfont.woff') format('woff'),
url('../fonts/DroidSerif-Regular-webfont.ttf') format('truetype'),
url('../fonts/DroidSerif-Regular-webfont.svg#DroidSerifRegular') format('svg');
font-weight: normal; font-style: normal;
}
  • Js постоянно изменяется,
  • добавляются новые функции,
  • удаляются старые,
  • усложняется интерфейс и взаимодействие с ним,
  • увеличивается объем кода,
  • увеличивается взаимосвязь между элементами,
  • увеличивается сложность кода,
  • усложняется навигация по коду и поиск нужной функциональности,
  • остаются устаревшие функции, которые уже не используются, но присутствуют в коде,
  • когда над проектом работают несколько разработчиков, приходится постоянно "мержить" js,
  • и много других мелких факторов.

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

Что нам нужно

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

Как мы это сделали

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

Вся архитектура состоит из 3х базовых компонентов:

  1. Базовый модуль и класс
  2. Медиатор
  3. Модули

Рассмотрим более детально каждый из них.

Базовый модуль и класс

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

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

Медиатор

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

Модуль

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

Итоги

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

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

В завершении хочу привести цитату из отличной книги "Дао Toyota":

Джеффри Лайкер, "Дао Toyota"
Оптимальное сочетание философии, процесса, человеческих ресурсов и решения проблем создает обучающуюся структуру. Я убежден, что любая компания, которая занимается производством или предоставлением услуг, должна стать обучающейся структурой, если она хочет преуспеть в долгосрочной перспективе.

Что еще почитать на эту тему: