В связи с тем, что интерфейсная часть приложений становится все более сложной, использование клиентских MVC-инфраструктур JavaScript поможет вам справиться с проблемами Ajax. Учитывая большое количество таких инфраструктур, порой бывает трудно понять, с какой из них следует начать. В этой статье приводится краткий обзор некоторых наиболее популярных инфраструктур: Backbone.js, Spine.js, Knockout.js и Batman.js. Узнайте о том, как правильно выбрать инфраструктуру для своего следующего проекта.

Питер Белл, старший вице-президент по проектированию, General Assembly

Peter BellПитер Белл (Peter Bell) является старшим вице-президентом по проектированию и старшим научным сотрудником в General Assembly университете технологий, проектирования и предпринимательства. Он выступает на международных симпозиумах и много пишет о языке JavaScript, проблемно-ориентированных языках, гибкой архитектуре, NoSQL, а также предъявляемых требованиях и оценках. Питер выступал с докладами на многих конференциях, включая DLD Conference, ooPSLA, RubyNation, Code Generation, конференцию British Computer Society Software Practices Advancement и Rich Web Experience. Статьи Питера публиковались в журналах IEEE Software, Dr. Dobbs на портале IBM developerWorks, в журналах Information Week и GroovyMag.



13.12.2012

Введение

Пятнадцать лет назад многие из нас создавали Web-сайты с использованием таких инструментальных средств, как Perl и ColdFusion. Мы часто писали сценарии, которые обращались к базе данных в верхней части страницы, применяли необходимые преобразования данных и выводили эти данные в нижней части того же сценария. Подобная архитектура отлично работала при добавлении на Web-сайт какой-нибудь простой формы типа «Обратитесь к нам». Однако по мере того как приложения становились все более сложными, данный подход перестал справляться с возникающими задачами. В настоящее время большинство Web-приложений опираются на стандартную архитектуру «модель-представление-контроллер» (MVC) с отдельным кодом, отвечающим за бизнес-логику, логику отображения и логику взаимодействия с пользователем (маршрутизации). Появилось множество инфраструктур, от Spring MVC до Rails, которые могут помочь вам быстро реализовать Web-приложения на основе MVC.

Часто используемые сокращения

  • JSON: JavaScript Object Notation(Объектная нотация JavaScript)
  • MVC: Model-View-Controller(модель-представление-контроллер)
  • REST: Representational State Transfer(Передача состояния представления)

Несколько лет назад основной библиотекой для создания клиентских JavaScript-приложений была jQuery. Однако с увеличением сложности языка JavaScript в наших приложениях библиотека jQuery, по-прежнему оставаясь необходимой, перестала справляться с возросшим уровнем сложности задач. Например, одностраничное приложение для списка текущих дел может включать в себя список неотложных дел, полный список текущих дел, список дел на сегодня и список просроченных дел. Что происходит, когда вы удаляете какой-либо из этих списков? Если дело является неотложным и просроченным, возможно, вам придется вручную писать код для удаления этого дела из трех или четырех разных позиций в окне представления. Если после удаления какого-либо объекта вам необходимо удалить или изменить другие отображаемые на экране связанные объекты, сложность может стать непреодолимой.

Клиентские инфраструктуры MVC предназначены для решения подобных проблем, и большинство из них хорошо справляется со своей задачей. Но как решить вопрос о типе используемой инфраструктуры? В настоящее время доступно много клиентских MVC-инфраструктур JavaScript. В этой статье приводится общий обзор некоторых наиболее популярных инфраструктур. Узнайте о том, как правильно выбрать инфраструктуру для конкретного сценария использования.


Backbone.js

На сегодняшний день самым популярной и признанной клиентской инфраструктурой MVC является Backbone. Она широко используется многими сообществами; ее активно внедряют разработчики Rails на таких популярных ресурсах, как Backbone on Rails от thoughtbot — авторитетного консалтингового центра Rails (см. раздел Ресурсы). Преимущество инфраструктуры Backbone.js заключается в ее отличной интеграции с Web-сервисами RESTful. Если вы используете для обработки своих внутренних данных модель объектной нотации JavaScript (JSON) RESTful и следуете соглашениям, которые предполагает Backbone (соответствующим соглашениям, используемым в Rails), то для подключения Backbone к серверу вам не придется писать никакого кода, что позволяет сэкономить много времени.

В Backbone приложение включает в себя коллекции (пользователи или статьи), модели (один пользователь или одна статья), представления и маршрутизаторы. Представления в Backbone.js являются непредписывающими, что позволяет вам использовать свою любимую инфраструктуру создания шаблонов или визуализации JavaScript. Маршрутизаторы (комбинация маршрутизаторов типа Rail и традиционного контроллера MVC) отвечают за прием конкретного URL-адреса и информирование инфраструктуры о том, какой код требуется выполнить. Пример кода маршрутизатора Backbone.js приводится в листинге 1.

Листинг 1. Пример кода маршрутизатора Backbone.js
var Workspace = Backbone.Router.extend({

  routes: {
    "help":                 "help",    // #help
    "search/:query":        "search",  // #search/kiwis
    "search/:query/p:page": "search"   // #search/kiwis/p7
  },

  help: function() {
    ...
  },

  search: function(query, page) {
    ...
  }
});

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

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

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


Spine.js

Инфраструктуру Spine.js часто сравнивают с Backbone.js; Backbone.js повлияла на создание инфраструктуры Spine.js, и они близки по уровню признания. В состав Spine.js входят классы, модели, контроллеры и представления, которые являются немного более традиционными по сравнению с коллекциями, вводимыми инфраструктурой Backbone.js.

Инфраструктура Spine.js написана на языке CoffeeScript (см. раздел Ресурсы), что делает эту инфраструктуру более сжатой и (по моему мнению) упрощает чтение исходного кода. Для понимания того, как работает Spine.js, вам необходимо ознакомиться с языком CoffeeScript. При этом вам не требуется создавать свои приложения Spine.js на языке CoffeeScript. Однако если вы все же осуществляете разработку на языке CoffeeScript, для вас становятся доступными такие специфические возможности CoffeeScript, как классы. В JavaScript используется прототипичное, а не классическое наследование, поэтому собственные средства поддержки классов в JavaScript отсутствуют. В CoffeeScript применяется ряд достаточно стандартных моделей предоставления классов тем разработчикам, которые хотят их использовать. Если вы пишете свои приложения Spine.js на обычном JavaScript, вы можете просто использовать Spine.Class: var Users = Spine.Class.sub();, что предоставляет доступ к классам без написания кода на языке CoffeeScript.

Модели, контроллеры и представления в Spine.js реализованы с использованием классов, поэтому вы можете писать как методы классов, так и методы экземпляров. Модели отвечают за бизнес-логику и являются модулями; вы можете расширять их и включать другие модули для многократного использования свойств и функций со смешением стилей. Модели могут автоматически сериализоваться посредством JSON для сохранения с использованием простого локального хранилища. Или же вы можете обрабатывать сохраняемые объекты для сервера с использованием комбинации асинхронного JavaScript + XML (Ajax). Подобно Backbone.js, Spine.js теперь предоставляет разумные умолчания для сохранения с использованием Ajax, хотя при необходимости можно легко написать свою собственную нестандартную реализацию. В листинге 2 приводится пример кода CoffeeScript из приложения Spine.js.

Листинг 2. Код CoffeeScript из приложения Spine.js
class Contact extends Spine.Model
  @configure "Contact", "first_name", "last_name"

  @filter: (query) -> 
    @select (c) -> 
      c.first_name.indexOf(query) is not -1

  fullName: -> [@first_name, @last_name].join(' ')

Самым важным различием между Spine.js и Backbone.js является то, как они обрабатывают взаимодействие с сервером. Backbone.js ожидает реакции сервера, прежде чем отобразить ответ. Если вы попытаетесь удалить, вставить или обновить какой-либо элемент, пользовательский интерфейс (UI) не будет обновлен до момента успешного завершения операции. В Spine.js акцент делается на немедленном обновлении UI, при этом код Ajax сервера обрабатывается в фоновом режиме. Такой порядок обновления является существенным практическим и философским отличием, которое следует принимать во внимание при выборе между этими двумя доведенными проработанными, популярными и хорошо задокументированными инфраструктурами.

Если вы в первую очередь заботитесь о создании впечатления от клиентской части, а обновления информации о состоянии сервера второстепенны, возможно, лучшим выбором для вас будет Spine.js. Если же вы в первую очередь используете сервер для проверки достоверности изменений состояния, вероятно, вам больше подойдет Backbone.js. Инфраструктура Spine.js предоставляет более отзывчивый пользовательский интерфейс. Однако что произойдет, если инфраструктура отобразит уведомление об успешном удалении какого-либо элемента только для того, чтобы сервер отправил ответ, что вам не разрешено удалять этот элемент, поскольку он используется кем-то еще? Существуют и обходные пути, но в общем случае Spine.js лучше подходит для тех сценариев использования, в которых пользователи работают с собственными (а не совместно используемыми) данными. Например, одним из распространенных сценариев использования Spine.js является корзина для виртуальных покупок, где все ограничения проверки данных обрабатываются на клиентской стороне.


Knockout

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

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

В Knockout.js вы создаете модели, модели представлений и сами представления. Модели, как и в Spine.js с Backbone.js, отвечают за бизнес-логику, проверку данных и Ajax для взаимодействия с удаленным сервером — если только вы не создаете всего лишь локальное приложение. Модели представлений представляют собой код, отвечающий за хранение данных моделей и работу с этими данными. Например, модель представления может содержать методы для добавления, изменения и удаления элементов из списка. Модель представления располагается ближе всего к контроллеру в традиционной архитектуре MVC. Представления – это шаблоны, которые содержат разметку для визуализации информации на экране. В Knockout.js они могут декларативно связываться с моделями представлений (что позволяет легко начать работу с инфраструктурой). Некоторым студентам хватает примерно одного часа на то, чтобы начать работу с Knockout, а по окончании трехчасового учебного занятия они уже способны создавать нетривиальные приложения.

Как правило, инфраструктура Knockout.js хорошо подходит для небольших простых проектов. Для более крупных и сложных проектов люди чаще выбирают Backbone.js или Spine.js. Тем не менее опытные разработчики могут создавать с помощью Knockout.js сложные приложения, столь же удобные для администрирования. Если вы рассматриваете возможность выбора инфраструктуры Knockout.js, вам также следует рассмотреть Angular.js и Sammy.js (см. раздел Ресурсы), представляющие собой относительно облегченные инфраструктуры, с которыми можно легко начать работу.


Batman.js

Batman.js, интересная новая инфраструктура, была официально представлена на конференции JSConf в 2011 году, хотя стала доступной для загрузки только несколько месяцев спустя. Batman.js набирает поддержку среди программистов, которым нравится подход данной инфраструктуры к разработке приложений MVC. На первый взгляд, инфраструктура Batman похожа на Knockout.js с точки зрения легкости освоения и поддержки декларативных связываний в представлении. Batman.js предоставляет и некоторые другие возможности, включая необязательную полностековую инфраструктуру для автоматизированных генераторов кода, инструментальные средства сборки и даже внутренний серверный код node.js для реализации ваших серверных API.

Подобно Knockout.js, в Batman.js используются связывания представлений. Образец кода представления приводится в листинге 3.

Листинг 3. Образец кода представления в Batman.js
<ul id="items">
    <li data-foreach-todo="Todo.all" data-mixin="animation">
        <input type="checkbox" data-bind="todo.isDone" data-event-change="todo.save" />
        <label data-bind="todo.body" data-addclass-done="todo.isDone" 
            data-mixin="editable"></label>
        <a data-event-click="todo.destroy">delete</a>
    </li>
    <li><span data-bind="Todo.all.length"></span> 
       <span data-bind="'item' | pluralize Todo.all.length"></span></li>
</ul>

Код, приведенный в листинге 3, представляет собой допустимый код HTML5 с дополнительными атрибутами, которые Batman использует для связывания данных и событий. В Batman.js приложение состоит из моделей, представлений и контроллеров. Модели поддерживают проверку данных, имеют возможность реализовывать события жизненного цикла, включают встроенную коллекцию идентичности и могут получать указания (в виде активной записи) о том, как сохранять самих себя с использованием Batman.LocalStorage, Batman.RestStorage, Batman.RailsStorage или вашей собственной нестандартной реализации. Представления являются классами JavaScript, которые осуществляют визуализацию шаблонов, написанных на «чистом» HTML, где для связывания данных моделей и активации обработчиков событий используются атрибуты data-*. Контроллеры представляют собой постоянные объекты, которые обрабатывают события из представлений, обращаются к данным моделей и выполняют визуализацию соответствующих представлений.


Выбор инфраструктуры JavaScript

Если вы работаете над каким-либо большим и долгосрочным проектом, имеет смысл рассмотреть возможность использования Backbone.js или Spine.js в связи с их широким признанием и наличием технической поддержки по проблемам, с которыми вы можете столкнуться. Однако даже при работе над такими проектами необходимо понимать, что вам все равно придется писать больше инфраструктурного кода, чем потребовалось бы при использовании какой-либо устоявшейся серверной инфраструктуры MVC.

Стоит поэкспериментировать с одной из инфраструктур, использующих декларативные связывания в представлениях. Каждая из таких инфраструктур (например, Backbone.js) имеет свои сильные и слабые стороны. Если вы рассматриваете возможность использования декларативных связываний представлений, потратьте время на изучение дополнительных возможностей, предоставляемых более новой инфраструктурой Batman.js. Она менее популярна, чем другие инфраструктуры, но ее популярность стремительно растет, к тому же она предоставляет широкий спектр дополнительных функций, недоступных в простых клиентских инфраструктурых MVC.

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

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


Заключение

Клиентские инфраструктуры MVC JavaScript по-прежнему являются «незрелыми». Эта ситуация быстро меняется, и уже имеется несколько общепринятых передовых методик. Для более крупных проектов популярными вариантами с хорошей технической поддержкой являются Backbone.js и Spine.js. Если же вы предпочитаете декларативные связывания представлений, заслуживают дальнейшего изучения инфраструктуры Knockout.js и Batman.js.

Ресурсы

Научиться

  • Оригинал статьи: A survey of client MVC frameworks.
  • Backbone.js: узнайте о том, как представлять свои данные в виде моделей.
  • Backbone.js on Rails: узнайте о том, как лучше создавать интерактивные приложения с богатой функциональностью с использованием Backbone.js и Rails.
  • Spine.js: смотрите примеры, скринкасты, документацию и многие другие ресурсы.
  • Knockout: узнайте о том, как упростить динамические пользовательские интерфейсы JavaScript путем применения модели MVVM.
  • Batman.js: получите дополнительную информацию об этой инфраструктуре для построения Web-приложений с широкими возможностями с использованием языков CoffeeScript или JavaScript.
  • CoffeeScript: узнайте больше об этом маленьком языке, который компилируется в JavaScript.
  • Angular.js и Sammy.js: еще два инструментальных средства, которые хорошо работают с Knockout.js.

Получить продукты и технологии

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


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

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура
ArticleID=851799
ArticleTitle=Обзор клиентских MVC-инфраструктур
publish-date=12132012