Об использовании JavaScript-фреймворка Backbone.js написано много, но просто и кратко — мало. Я постараюсь исправить этот недостаток и рассказать разработчикам web-приложений максимально просто, доступно и кратко о том, зачем им может пригодится этот фреймворк и как, в общих чертах, он работает. Профессионалы и специалисты по Backbone.js: можете не тратить время, этот рассказ для новичков. Если быть честным, то для чтения этой заметки не обязательно быть Rails-developer'ом, надеюсь, статья пригодится всем, кто работает с любым из МVC-фреймворком.
Итак, представим себе среднестатистический проект, использующий MVC подход. Это, вероятно, будет интернет-магазин с несколькими моделями (около 10-15 обычно), связанными друг с другом различными видами отношений. Проект будет иметь соответственное количество контроллеров, 2-3 layout'а для разных устройств вывода, несколько контроллеров в namespace'е /api/v1, масса view'шек и partial'ов. Всё это работает стандартно, браузер шлёт запросы, контроллеры делают выборки данных, передают их во view'шки, те, в свою очередь, отсылаются пользователю в браузер. Есть функция «Поиск», которая ищет определённые экземпляры какой-то модели, есть view для результатов, содержащая цикл, который создаёт на странице отображение этих найденных экземпляров, есть даже мобильное приложение для Android, которое общается с Вашим серверов через API (запрашивает контроллеры, которые ждут в namespace'e /api/v1, кстати, часто дублирующие аналогичные 'обычные' контроллеры, только отдающие информацию в другом виде).
Теперь включаем режим Ванги. Я знаю, что в проекте обязательно есть некоторое количество кода на JavaScript. В различных веб-приложениях JavaScript'ом решаются разнообразные задачи — почти везде используется jQuery с плагинами или без, jQuery UI и прочие другие модули и плагины. Мы не будем рассматривать здесь использование JavaScript для создания всякого рода эффектов, выпадающих меню, drap&drop'ающихся элементов и прочее, что относится к украшательствам, мы рассмотрим работу с данными.
Итак, режим Ванги позволяет мне предположить, что вас есть модель Product (у нас ведь интернет-магазин, помните?) и безусловно есть интерфейс менеджера, который может вывести себе список товаров по некоторому критерию. У менеджера, есть стилизованный индикатор количества новых заказов, чтобы сразу же, как можно быстрее увидеть, что появился новый заказ. Я думаю, что этот индикатор работает так: в document.ready() вы сделали таймер и раз в 60 секунд запрашиваете адрес вроде /api/v1/kolichestvo_zakazov. Ну или /api/v1/orders/new/count, смотря по вашему отношению к лингвистике. В функции, которую запускает таймер у вас есть написанный на jQuery ajax запрос, который получает по ранее указанному URL'у какие-то данные. Почему какие-то? Я не знаю, Ванга не поможет. Один программист может в ответе слать корректный json вроде {orders: {new: 3}}, другой может слать просто цифру 3. Третий может на стороне сервера отрендерить и прислать в ответе целый кусок html-кода, пригодный сразу к вставке в нужное место документа. В общем, Ванга тут не поможет, тут нет никакого порядка, закона и максимальный уровень неожиданности. Но самое главное — данные, после получения, просто говоря, теряются. Клиентская сторона получила что-то, сделала с этими данными что-то и они больше не принесут вам никакой пользы.
С точки зрения философа-перфекциониста — это ужасно. Согласитесь, если уже придуманы сотни способов упорядочивать данные на стороне сервера (MVC-подход, любая СУБД — это по своей сути методологии упорядочивания информации), стало быть нужно сделать следующий шаг — упорядочить данные на стороне клиента.
Что же нам может предложить Backbone.js? Первое, на мой взгляд, самое главное, это именно упорядочивание данных, которое в Backbone.js реализуется через знакомый нам MVC. Кратко о том, как это будет:
1. У вас в приложении есть модели. User, Product, Order… Отлично, с Backbone.js Вы сможете описать эти модели на стороне клиента! И эти модели будут настоящими, вы сможете создавать новые экземпляры, редактировать поля уже имеющихся, удалять ненужные. Вы можете не писать какие-то функции, для получения какой-то информации, которая потом будет выброшена, получайте с сервера экземпляры класса order. Быть может, order будет содержать много лишней информации, подумает кто-то, нужно было же только количество! Может быть. Но никто не запрещает передавать в JSON'е только нужные на стороне клиента поля order'ов. А ваш гипотетический менеджер вдруг может захотеть кроме количества заказов видеть ещё и суммы каждого — а у нас уже всё готово, информация уже там, только покажите её, обьекты уже у клиента и синхронизированы с сервером. А если менеджер захочет прямо на месте изменить эту сумму? Не проблема. Намного приятнее написать в коде order.save( {:cost => this.input.val(} ), чем писать новую самодельную функцию. Модели будут знать URL, куда слать GET, POST, PUT и DELETE запросы и будут делать это сами, когда нужно. Например, product.delete() самостоятельно отправит DELETE на /api/v1/products/75 (75 это id этой модели).
2. У вас в приложении есть страницы, где обязательно есть множество однотипных блоков. Результаты поиска товаров тому пример. Каждый товар может быть расположен внутри какого-нибудь . После создания этой страницы на сервере, связь этой области с товаром, в ней описанным теряется. Если Вы захотите что-нибудь делать на этой странице, вам придётся изобрести способ снова дать знать этой области с каким она товаром связана, например дать data-атрибут с id продукта и использовать его в формах и запросах… Backbone.js реализует такую привязку сам. Это будет называться View и будет делать даже больше: область продукта может реагировать на изменения продукта и перерисовываться сама, к примеру. Внутри области вам будет доступен экземпляр класса Product, именно тот самый, и вы сможете делать с ним всё, что угодно на стороне клиента. Не забудьте после сделать ему save(), чтобы Backbone.js сохранил ваши изменения на сервере.
Кстати. Хотите фильтр по некоторому полю таблицы товаров? Уже догадались, что это вообще не требует никаких дополнительных действий? Не надо ничего отправлять на сервер, получая ту же таблицу, только отфильтрованную, заново. Обьекты-то у вас уже есть, просто отфильтруйте коллекцию product'ов одной строкой кода на javascript. И да, они ещё и перерисуются сами, вам об этом нужно позаботиться всего лишь один раз, сообщив Backbone'у, что вы хотите обновлять кусок страницы, где находится информация об этом product'e при изменении product'a.
3. И ещё в тему упорядочивания данных. Используя MVC-фреймворк на стороне клиента вы, в некоторых случаях, можете свести трафик между клиентами и сервером к обмену небольшими кусками json'а, что позволит экономить огромное количество трафика. Вы будете передавать клиентам и получать от клиентов только данные, вы не будете постоянно пересылать клиентам полные страницы. Весь javascript и css может быть загружен единожды и закеширован, дальше будет происходить только обмен упорядоченными как вам удобно данными.
Вместо заключения: конечно, в этой заметке не затронуто и 5 процентов возможностей Backbone.js, но я хотел рассказать не о нём, а о самой идее поддерживать информацию в порядке как на сервере, так и в браузере. Разработчики ПО занимаются упорядочиванием окружающего мира, мы делим мир на модели, выявляем их свойства, их поведение, состояние и взаимодействие. Быстро меняющийся Интернет практически не следует стандартам (а в отношении клиентского контента вообще никаких стандартов нет, кроме 4х или 5ти спецификаций CSS, которые далеко не лучший пример порядка). Так давайте же увеличивать энтропию этого хаоса хотя бы таким удобным способом — будем держать данные в структурном порядке и в синхронизированном состоянии!
Спасибо за внимание, с уважением разработчик-перфекционист.
P.S. Если статья окажется интересной сообществу, напишу продолжение, с примерами, что изменится к лучшему при использовании Backbone.js на примере магазина, который был описан в начале статьи.
Автор: Alve