Gaperton (gaperton) wrote,
Gaperton
gaperton

Categories:

4. BackboneJS.

Допустим, у нас есть группа разработчиков на PHP, которые знают чуть чуть JS и jQuery. Что самое простое мы можем сделать, чтобы начали писать браузерное приложение, и были продуктивны немедленно?

Мы можем попробовать использовать тот же принцип, и те же архитектурны правила, к которым они привыкли в PHP. У них были шаблоны с встроенным PHP? Отлично, мы будем использовать такие же шаблоны со встроенным JS, которые будут разворачиваться в браузере. Они использовали jQuery? Отлично, мы сохраним jQuery.

Нам остается задать этому какую-то структуру. Элемент UI - это будет объект View с присоединенным DOM-элементом, и методом 'render', который должен разворачивать шаблон в присоединенный элемент. Помимо этого, View должен уметь перехватывать события UI, и вызывать свои методы.

Помимо этого, нелишне добавить к этому простые средства для работы с REST API. Класс для кусочка JSON, который умеет создаваться/читаться/сохраняться/удаляться (CRUD) в каком-нибудь стандартном варианте REST. Назовем его Model. Раз у нас REST, то надо еще уметь получать их список. Значит, нужен еще Collection.

У нас сейчас получилось что? Правильно, самый популярный фреймворк для разработки в браузере - backbonejs (http://backbonejs.org), который, в сочетании с модульной системой позволяет из говна и палок собрать браузерное приложение.


Что мы видим глядя на архиутектуру Бэкбон? Два слоя, вью и модели. Однако, и вью, и модели совершенно "плоские". Логика авторов вполне понятна - в методе 'render' одного view совсем несложно подцепить другой view. Зачем навязывать людям какой-то способ это делать - пусть сами как хотят. А для точки протокола REST, которую представляет собой "модель", никакой "рекурсивности" и не нужно - она одна, и все. Хочется хранить в атрибуте модели сложный JSON? Да на здоровье.

Здесь мне полагается начать перебирать буковки чтобы описать паттерн, предоставляемый backbone - это MVC, MVVM, или что? На случай, если вам это действительно важно, какими буковками это называть (видел я таких, как определятся с буковками - сразу успокаиваются, начинают дышать ровнее, как будто поняли что-то. Или вбрасывают так - "это же MVVM!", и смотрят на тебя стеклянным глазом), то вообще-то это типичный PAC (https://en.wikipedia.org/wiki/Presentation–abstraction–control). Presentation - это шаблон, Abstraction - это модель или коллекция, а Control - это собственно сам View.

Не? Ну, тогда типичный MVP (https://en.wikipedia.org/wiki/Model–view–presenter), где презентер это опять вью, а вью - это шаблон. Не? Ну тогда я просто объясню, как оно работает :)

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

Зачем события? А вот тут мы приходим к фундаментальной проблеме веб платформы, предложить какое-то свое видение решения которой просто обязан каждый фреймворк. Штука в том, что JS исторически был однопоточен, и ввод-вывод из него делается асинхронно. То есть, когда вы запросили данные - вам их сразу в этом месте никто не даст. Сразу вы оставляете коллбэк, и они придут потом. И когда они придут - вы должны обновиться. Оставлять коллбэк невероятно неудобно, и разные фреймворки по разному подходят к этой проблеме.

Backbone использует очень простой подход. Мы пишем приложение, как будто данные у нас всегда есть, и как бы синхронно. Но - они по разным причинам могут обновляться (то, что они с сервера пришли - это частный случай), и мы всего-то должны - замечать это, и обновить UI. Поэтому, модели в backbone умеют бросать события 'change', а вью полагается его ловить и обновлять себя, вызывая 'render'. Выглядит это примерно вот так:

this.listenTo( this.model, 'change', this.render );
model.fetch();


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

model.fetch().done( function(){
    this.render();
}.bind( this ) );


Или, так сказать, опустится до коллбэка.

model.fetch({
    success : function(){
        this.render();
    }.bind( this )
});


Но для бэкбона идеоматической является модель программирования с событиями 'change'. И это - пожалуй, самая лучшая идея из всех, что есть в backbone.

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

Сейчас технологии разработки SPA ушли очень далеко вперед, и backbone явно устарел на фоне современных фреймворков. Его суровый солдатский дизайн не дает разработчику почти никаких сервисов. Но одно бесспорное достоинство backbone отметить надо. Дело в том, что техника, которую бэкбон предлагает вам для рендеринга HTML, а это как-то так:
render : function(){
    this.el.innerHTML = this.template( this.model );
}

принципиально самый быстрый способ рендеринга HTML из всех возможных. Он не просто "быстрее" чем всякие там Angular, React, и Ember, он их в тряпки нафиг рвет. Присваивание в innerHTML в десятки раз быстрее, чем DOM-манипуляции. В десятки, Карл.

И если вы делаете мобильное приложение, то, в принципе, это очень даже повод задуматься.
Tags: backbonejs, javascript, архитектура ПО
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 15 comments