Pull to refresh

Обзор JS-фреймворков. Путешествие через джунгли JavaScript MVC. Ч. 2

Reading time 15 min
Views 124K
Original author: Эдди Османи
(Окончание перевода статьи Эдди Османи о сравнении и выборе библиотеки для проекта со значительной ролью JS на клиенте.)
Содержание первой части:

■ Что такое MVC или, лучше сказать, MV*?
■ Когда нам нужен MV*-фреймворк JS?
■ Где же мы будем нуждаться в MV*, а где нет?
■ Проблема выбора: слишком много вариантов?
■ TodoMVC: общее приложение для обучения и сравнения
■ Предложенные нами критерии выбора фреймворка
■ Dojo и усложнение фреймворков на JavaScript
■ Коллекция TodoMVC (фреймворки, на которых сделаны реализации тестового приложения Todo)

■ Какой фреймворк когда следует использовать?


Для сужения круга поиска фреймворков хотим предложить выбор фреймворка высокого уровня по признакам, которые, надеемся, помогут отобрать несколько вариантов для проб.

Я хочу нечто гибкое, с решениями в стиле минимализма для разделения задач в моем приложении. Оно поддерживает постоянное подключение и REST-синхронизацию, модели, представления (с контроллерами), обмен данными, управляемый событиями, шаблонизацию и навигацию (по якорям в URL). При изменении модели немедленно изменяется представление. Я хотел бы сам в должной мере управлять архитектурой. Идеально, если решение использовалось у многих больших компаний для нетривиальных приложений. Поскольку у меня может получиться что-то сложное, я хотел бы видеть активное сообщество вокруг фреймворка, которому можно всегда попытаться поставить не слишком простые вопросы (Marionette, Chaplin, Aura, Thorax). Идеально иметь также инструменты сборки (grunt-bbb, brunch). Используйте Backbone.js.

Я хочу основу приложений десктопного уровня для Сети. Этот фреймворк должен быть высокоуровневым, модульным, MVC, без потребности собирать всё вместе вручную, поддерживать персистентность (постоянные объекты с метафорой файла, устройства), вычисляемые свойства и автообновление шаблонов. Это нужно для интеллектуального управления состояниями вместо ручной настройки, совместимость с многими смежными фреймворками. Это должно быть с хорошей документацией, с шаблонами пользования, инструментами сборки (ember.gem, ember for brunch). Используйте Ember.js.

Я хочу что-то легковесное, с подключением шаблонов на лету, навигацией, интеграцией с основными библиотеками (типа jQuery и Dojo) и быстрое, с поддержкой наследования компонентов MVC, что может быть ещё не отработано на крупных приложениях, но должно быть. Идеально, если сделано людьми с опытом создания сложных приложений. Используйте CanJS.

Я хочу оболочку декларативного стиля, использующую View для сбора данных о поведении пользователя через кастомизацию HTML и компонентов по правилам приложения. С простой поддержкой тестовой системы, с URL-навигацией и разделением задач через MVC или его вариант. Это даёт кастомизированный подход к смежным библиотекам, делающим компиляцию HTML, чтобы строить собственный DSL (предметно-ориентированный язык) в HTML. Это нужно для таких элементов сетевой платформы как веб-компоненты; и ещё надо иметь инструменты сборки (angular-seed). Используйте AngularJS.

Я хочу хорошую основу для объёмных приложений, с проверенной и отработанной инфраструктурой виджетов, модулей с постзагрузкой; возможно — с асинхронной и простой интеграцией с CDN-ами, с выбором модулей и виджетов (графики, диаграммы, таблицы, и т.д), с хорошей мультиязычностью (i18n, l10n). Нужна поддержка ООП, MVC и сборщик из блоков (модулей) для создания сложных архитектур. Используйте Dojo.

Я хочу что-то оптимизированное под работу с расширениями YUI. С поддержкой моделей, представлений и навигации, что сделало бы простым написание приложения с разными способами отображения информации, с переходами вариантов отображения из одного в другой и подобное. Это — полное решение с виджетами/компонентами, со способностью описать архитектуру приложения. Могут быть инструменты сборки (yuiproject), но с возможной заменой на другие. Используйте YUI.

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

Я хочу инструмент построения сложных динамических UI на основе модели данных и декларативного стиля связывания. Для обновлений UI при изменениях модели, используя двунаправленное связывание и поддержку зависимостей через отслеживание данных. Я должен быть в состоянии использовать это с любым фреймворком или даже с готовым приложением. Нужно иметь встроенную шаблонизацию и легкую расширяемость. Используйте KnockoutJS.

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

■ Что разработчики думают о самых популярных фреймворках?


Как часть исследования по MV*-фреймворкам для TodoMVC и этой статьи, мы провели опрос среди разработчиков. Какой фреймворк они чаще используют, и главное, почему бы его порекомендовали? Что они почувствуют, если бы этого фреймворка не было в проекте?

Вот некоторые самые интересные ответы:

Ember.js

«за»: комбинация живых шаблонов и связанных (observable) объектов изменила способ работы с JavaScript. Вначале он может показаться несколько замороченным, но работу заканчиваете с хорошим разделением ответственности в коде. Я обнаружил, что как только у меня все описано, добавление довольно сложных особенностей занимают пару строк. Без Ember эти те же особенности были бы адски сложными в реализации.

«против»: Ember, всё-таки, должна достигнуть версии 1.0. Много вещей ещё в движении, таких как маршрутизатор и Ember data. Новый вебсайт очень полезен, но нет такой документации для Ember, как у других фреймворков, особенно Backbone. С таким количеством магии в фреймворке это немного страшно. Если что-то ломается, вы не сможете выяснить точно, почему. Да и сообщения об ошибках в Ember часто неточны.

«за»: ключевые факторы:
a) Особенности, которые позволяют мне избегать массы шаблонного кода (привязки, вычисляемые свойства, слой представления с хорошим управлением).
b) команда разработки. Я — рубист и знаю, чего стоит Yehuda Katz. Я доверяю парню =).

«против»: документация. Действительно грустно, что у Ember нет хорошей документации, обучающих программ, скринкастов как у Backbone, Angular или других фреймворков. Прямо сейчас мы просматриваем код, ища документацию, которая не идеальна.

«за»: соглашение по конфигурации. Ember принимает много мелкой работы за вас; это — безусловно, самый легкий способ построить приложение на стороне клиента в наши дни.

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

«за»: простота связывания, плотная интеграция с управлением, легкая модульность в моем собственном коде.

«против»: я хотел бы иметь устойчивую интеграцию с Ember data и интегрированную поддержку localStorage, синхронизированную с REST API — всё это несбыточные мечты.

Backbone.js

«за»: простота — только 4 основных компонента (Коллекция, Модель, Представление, Маршрутизатор). Огромное сообщество (экосистема) и много решений на StackOverflow. Фреймворки высшего порядка типа Marionette или Vertebrae — с большим количеством умного кода внутри. Кому-то нравится «низкий уровень» — надо написать много шаблонного кода, но получить сделанную под себя архитектуру.

«против»: мне не нравится наследование — копируется содержание родительского объекта в новый. Нужно прототипное наследование. Иногда я не читаю «real world scenarios» в примерах из доков. Приходится делать большое исследование после чтения туториала с TODO, чтобы выяснить, как построить чуть более сложное приложение.

Я не использую официальную поддержку AMD в проектах от DocumentCloud (Backbone, Underscore) [но это не проблема с новым методом shim() в RequireJS 2.0].

«за»: после начального головоломного изучения работы Backbone всё это оказывается крайне практично. Практичность — в хорошо поддержанной, легковесной и постоянно обновляемой библиотеке в правильном окружении. Дружественная поддержка Underscore, jQuery/Zepto, инструменты, с которыми работало бы большинство проектов из моей студии.

«против»: количество обучающих программ о том, как работать с Backbone — разное для разных версий. Я попросил других разработчиков взглянуть на Backbone, и они написали бы код для версии 0.3. Неосознанно. Пока нет проблем, Backbone может это исправить, но это, пожалуй, главное неудобство, с ней связанное.

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

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

«за»: обеспечивает только минимальную абстракцию без необоснованных ограничений — даёт возможность собирать проект по потребностям.

«против»: я переписал бы или удалил Backbone.sync. Он построен для протокола HTTP и плохо приспосабливается к особенностям WebSocket.

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

«против»: факт, что нет никакого связывания представления по умолчанию (хотя можно задать его). Обновление всего представления, когда меняется единственное свойство, неэкономично.

У REST API есть много плюсов, но есть трудности при большом количестве записей (по общему признанию, проблема с REST — её собственная, но все еще остаётся) и неприятные проблемы в получении различных схем URI для работы с различными типами операций.

AngularJS

«за»:
a) Двунаправленное связывание данных — очень сильный подход. Вы думаете больше о вашей модели и состоянии вместо организации ряда событий. Модель — единственный источник правды.
b) Скорость. AngularJS легко загружаем. Он шаблонизирует построением узлов вместо innerHTML, что, по идее, производительнее.
c) Если вы ориентируетесь на современные браузеры и/или достаточно бережливы, можете обойтись без jQuery.

«против»: я хотел бы уметь указывать переходы состояний UI, изменяемые моделью. А именно, элементы, использующие ng-show / ng-hide, я хотел бы скрывать или сворачивать простой декларацией.

«за»: Он очень интуитивен, с отличной документацией. Мне нравится их подход к связыванию данных, HTML, основанный на Views, вложенные окружения (scopes). Я переходил от Backbone/Thorax к Angular и никогда не оглядывался назад. Новое расширение (addon) Chrome Batarang интегрируется с Chrome Developer’s Tools и даёт доступ в реальном времени к структурам данных Angular.

«против»: хотелось бы иметь встроенную поддержку функций типа drag-n-drop, но это может быть добавлено через внешние компоненты, доступные на GitHub. Хотел бы видеть больше сторонних компонентов, подходящих для повторного использования. Я думаю, что это — только вопрос времени для экосистемы вокруг AngularJS, чтобы стать более зрелым, и затем они будут доступны и разнообразны, как в сообществах типа jQuery.

«за»: Он решительно уменьшает шаблонный код, позволяет повторно использовать код через компоненты, расширяет синтаксис HTML так, чтобы много сложных возможностей стали так же просты, как написание атрибутов в HTML, и крайне легко тестируемыми благодаря полному описанию зависимостей.
Вы можете написать нетривиальное приложение без jQuery, без непосредственного управления DOM. Сделать такой инструмент — настоящее мастерство.

«против»: еЕго порог изучения несколько выше, чем у Backbone (который весьма легок для мастера), но результат стоящий. Документация могла бы быть лучше.

KnockoutJS

«за»: я не всегда его использую, но KnockoutJS великолепен для одностраничных приложений. Очень легкая подписка на изменения объектов; намного лучше API для так называемой в Backbone “collection views”, используя наблюдаемые (observable) массивы. И пользовательские события на наблюдаемые объекты для эффектов, и т.д.

«против»: чувствется, что API трудно расширить; я, вероятно, предпочел бы выбрать Backbone на больших приложениях (в том числе, из-за поддержки сообщества).

«за»: мне нравится механизм связывания данных и его удобное использование. Особенно нравится, как заменили шаблоны на привязывание (binding) управляющей логики.

«против»: плохо, что нет никакого руководства по лучшим практикам со структурой приложения. Кроме наличия View Model, фреймворк не помогает вам в описании хорошо структурированной View Model. Это очень легко закончится большой неуправляемой функцией.

Dojo

«за»: синтаксически — Dojo очень простой. Это хорошо для динамических и устойчивых сборок, с начальным файлом подгрузчика, обычно размером 6 КБ. Это AMD-совместимый (допускающий постзагрузку), что делает его очень компактным, и приходит «из коробки» с тонной расширений, от базовой работы с DOM до сложного SVG, VML и canvas. Система виджетов Dijit великолепна в простоте использования и способности к расширению. Это очень хорошо подобранный и полный набор инструментов.

«против»: dojo/_base/declare функциональность — не 100%-ый строгий управляемый инструмент, сейчас есть некоторые накладки из-за обратной совместимости, хотя это в основном исправится в Dojo 2.0.

«за»: хХорошие компоненты: табы, таблицы для данных, менеджер форм… Одинаково для всех браузеров. Работающий AMD. Легкие тесты с имитаторами данных. Хорошо интегрируется с другими фреймворками благодаря AMD (я буду интегрировать с JMVC).

«против»: проект настроен по умолчанию для вышедших из моды компонентов. Не полностью html5. Документация — так себе. Плохая система шаблонизации (никакого связывания «на лету»).

YUI

«за»: YUI3 — модульная и типа «делай-что-хочешь» библиотека компонентов, которая включает все достоинства Backbone и даже больше. Она, на мой взгляд, даже улучшает некоторые концепции Backbone, разделяя некоторые вещи (например, атрибут — отдельный модуль, который может быть подмешан в любой объект — «модуль» события может быть тоже подмешан).

«против»: я хотел бы видеть, что YUI3 поддерживает автоматическое связывание (wiring) из Ember. Думаю, что это действительно большое достижение для Ember; в остальном, вижу YUI3 превосходной библиотекой компонентов, где можно подобрать то, что требуется. Хочу видеть улучшенную AMD-совместимость загрузчика модулей. Он сегодня работает хорошо, но было бы лучше, если я мог бы начать новые проекты на модулях AMD и вставлять в компоненты YUI3 и другие вещи третьих сторон, которые тоже используют AMD.

JavascriptMVC

«за»: Имеет все инструменты «из коробки», остаётся только запустить команды и начать сборку. Я использовал 6 месяцев, и это было действительно хорошо.

«против»: единственная вещь, которую я хотел бы видеть — ускорение развития следующей версии. Разработчики знают о проблемах и решают их, но процесс мог бы быть другим — не месяцы на некоторые проблемы, которые я хочу исправить и отправить решение — тогда я мог бы сделать патч и пулл-реквест.

Maria

«за»: поскольку Maria — фреймворк реализации чистого MVC, она сосредоточена на том, чтобы быть фреймворком MVC. Не больше и не меньше. Всё строго и просто.

«против»: немного больше документации, чем написано в исходном коде плюс несколько тесткейсов. Не помешал бы туториал, показывающий основы реального использования MVC в Maria.

Cujo.js

«за»: для реальных приложений почти никогда не бывает достаточно MV* из коробки, и самый важный инструментарий часто вне коробки. С cujo.js — вы определяете коробку.

Да, cujo.js имеет высокоуровневые MV*-подобные возможности для создания Views, моделей, контроллеров, и т.д., но каждое приложение различно, и никакой фреймворк не может быть 100%-ым решением. Вместо попытки угодить всем, cujo.js даёт в том числе и низкоуровневые инструменты, настройку архитектуры и богатую систему плагинов, которая может даже объединить и расширить другие MV*-фреймворки.

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

«против»: широкие массы джаваскриптеров совершенно неподготовлены и не обучены развитию крупномасштабных приложений. Большинство из них даже не знает о существовании паттернов проектирования и архитектур.

Так как cujo.js так отличается от других, он нуждается в нечто большем, чем просто отсылка к API и примерам кода. Без обучающих программ, образовательных материалов, и развивающих примеров cujo.js будет выглядеть странным и угнетающим для ненамётанного глаза, но скоро ожидается документация.

ExtJS

«за»: думаю, ExtJS работает лучше всего вместе с Ext Designer. Он отделяет себя от других GUI-фреймворков, позволяя непрограммистам макетировать UI, а программисты заполняют пробелы. Сравнение с фреймворками MVC типа Backbone, на мой взгляд, неправомерно: сила ExtJS — в создании богатого GUI, а не легковесных веб-приложений.

Для коммерческих, удалённых офисных, rich-приложений думаю, что ExtJS остается лучшим выбором, когда дело доходит до решений на JavaScript (кроме GWT и т.д). Для публичных веб-приложений я имею кое-что другое, дающее мне больше контроля над разметкой (и идеально отрабатывающее greaceful-деградацию).

«против»: у него высокий порог вхождения, выше многих других современных структурных (structural) фреймворков. Можно сказать, что если вкладывают капитал в ExtJS для долгосрочных разработок, время на изучение окупится, однако думаю, что решения типа этого должны стремиться минимизировать время обучения команды.

«за»: думаю, что особое свойство ExtJS 4 — что он бросает вас в понятия MVC и требуемую структуру файлов с места в карьер. Начальные обучающие программы Dojo, говорят главным образом об улучшении существующих сайтов, а ExtJS предполагает, что вы начинаете делать сайт с нуля.

ExtJS действительно, вообще не показывает, что вы имеете дело с HTML. Библиотека компонентов достаточно богата, чтобы долго работать, не касаясь HTML при построении приложения.

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

«против»: лицензирование считают ограничительным и оно трудно понимаемо некоторыми. Больше людей вложило бы капитал в ExtJS, если бы было понятнее, каков задаток и каковы долгосрочные затраты при использовании. Таких проблем нет с некоторыми другими структурными инструментами, но это, вероятно — не повод для беспокойства в условиях большого бизнеса.

«за»: ExtJS — фантастический пакет для быстрого построения RIA для интранета. Я, например, люблю писать с HTML и JavaScript, и для меня есть большое удовлетворение копаться на этом уровне. Хотя ExtJS позволяет чувствовать, что вы не работаете с HTML, он, всё же, даёт много рычагов управления документом, особенно при создании сложного UI.

«против»: Тем не менее… я полностью соглашусь, что это очень тяжелая оболочка, и я не думаю, что порекомендую её для фронденда в вебе. Моя самая большая претензия к пакету, что это — бОльшая головная боль для тестов, чем я мог представить. Наш тестер закончил это тем, что переключился на Sikuli, потому что попытки работать в Selenium становились слишком большим сражением.

Batman

«за»: у него есть большая и удобная система просмотра связываний. Игры с Рельсами очень приятны и это — все требования по конфигурации.

«против»: документация могла быть намного лучше, и я чувствую, что Shopify не будет добавлять новые возможности, хотя говорят, что будут.

■ Не бойтесь экспериментировать


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

У меня был случай: я нашёл, что Batman.js требует минимум самописного кода в реализации. Я не постоянный CoffeeScript-щик и не пользователь Batman.js, но результат дал мне пищу для размышлений. Возможно, что я смогу взять часть исходников инструмента и использовать у себя. Или, возможно, в будущем проекте я просто использую Batman.js, когда он обрастёт сообществом и поддержкой.

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

■ Выход за пределы понятий MV*


Хотя семейство MV* паттернов весьма популярно для структурирования приложения, они ограничены в том, что нет различия в разновидностях слоёв приложений, связи между разными Views, нет сервисов, выполняющих работы или прочего. Разработчики могут оказаться перед необходимостью исследовать другие паттерны.

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

Мне однажды понадобилось подобие паттерна Компоновщик. Я заметил, что разработчики в приложениях Backbone поняли, что была потребность в объекте, который координировал бы различные части приложения. Разработчики долго пытались решить это использованием элемента Backbone (например, Представления), даже когда в нем нет потребности. Вместо этого я исследовал потребность в приложении Initializer.

Я нашел, что MVC действительно не имеет способа работы с областями страницы или приложения. Суть управления областью — вы определяете видимую область экрана и задаёте самые общие данные о нём, не зная, какое содержание будет показываться во время выполнения.

Я создал решения для управления областями, инициализации приложений и с другими функциями в моем расширении проекта Marionette. Это — одно из многих решений, которые расширяет фреймворк (создаёт архитектурный паттерн) для разработчиков, сталкивающихся с необходимостью строить действительно сложные одностраничные приложения.

Есть даже приложение Marionette TodoMVC, доступное для желающих сравнить стандартное приложение Backbone с тем, которое работает вне обычного MV*.
         Derick Bailey — автор Marionette

Большая часть задач решается через JavaScript MVC, но некоторые решиться просто не могут. Например, приложение получило стороннее API во время выполнения, но не дало информации, как будут структурированы данные.

Я потратил почти год, пытаясь решить ту самую проблему, но в итоге пришёл к выводу, что втискивание этого в MV* было нежизнеспособно. Я имел дело с «аморфной моделью», и это — то, из-за чего всё развалилось. Другими словами, если у вас нет четкой модели, самые современные фреймворки JavaScript вам не помогут.

Вот здесь появились паттерны ядра J2EE. Я про них узнал, читая ­«PHP Objects, Patterns, and Practice», Matt Zandstra, и хорошо, что так случилось! Паттерны J2EE в основном описывают в общих чертах процесс, управляемый запросом, когда URL управляет поведением приложения. В двух словах, запрос создаётся, меняется, а затем используется для отрисовки представления.

Я подробно остановился на своём опыте с управляющими запросами и паттернами J2EE для всех, кто хочет научиться большему.
         Dustin Boston — соавтор Aura

■ Заключение


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

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

Экспериментирование с фреймворками ознакомит вас со способами решения общих проблем, которые помогут вам программировать лучше.

Благодарю моего коллегу, участника команды TodoMVC Sindre Sorhus за его помощь с поправками и вычиткой этой статьи.

Автор: Addy Osmani — инженер-разработчик в команде Chrome в Google. Будучи страстным разработчиком JavaScript, он написал книги со свободной лицензией распространения: «Изучение паттернов проектирования JavaScript» и "Разработка приложений Backbone", участвовал в развитии проектов с открытым кодом Modernizr и JQuery. В настоящее время работает над "Yeoman" — оригинальным рабочим процессом создания привлекательных приложений.
Tags:
Hubs:
+69
Comments 18
Comments Comments 18

Articles