Pull to refresh

Comments 33

Емнип когда то в бэкбоне были контроллеры. Но от них избавились, заменив классом Backbone.Router. Это более удобно для фронтэнда.

Еще не очень понял зачем это:
Application.extend = Backbone.Model.extend;
Controller.extend = Backbone.Model.extend;

Application.extend = Backbone.Model.extend;
Controller.extend = Backbone.Model.extend;
Это для того, чтобы можно было сделать так
myController = Backbone.Controller.extend({})
Router — это хорошо, но выполняет немного другие задачи.
Роутер — это та функциональность контроллеров, которую нельзя было выкинуть.Но сами контроллеры излишни. Нет ни одной причины, почему вьюшки не могут подписываться на изменение моделей.
Конечно связанность чуть больше, но мы не плодим сущностей, которые только и делают, что перенаправляют эвенты.
Я не оспариваю подход, я всего лишь показываю пример того, как можно решить проблему. Сам по себе backbone.application — это учебное пособие в каком-то смысле. Спорить о преимуществах MV перед MVC я не буду, не вижу в этом смысла.

Никакого оспаривания. Когда я начал заниматься бэкбоном у меня сразу возник вопрос а где контроллер Оо?, и идея реализовать свой.
В моём случае, я использовал backbone исключительно в определённых целях (см. visualHUD в примерах). Использовать роутер в качестве контроллера я не решился. Зато я решил развлечься и написать простенький application/controller. Результатом я остался доволен, пережитым опытом делюсь на хабре. Такие дела )
3-4 года назад меня «били чайником по голове» за аналогичное мнение. Все меняется и это хорошо)
За идею выкинуть контроллер?)
Ну без него действительно непривычно поначалу.
Нет, конечно. К чему в рабочем приложении проводить такой нешуточный рефакторинг. Разговор шел об архитектуре грядущего проекта. А я как раз экспериментировал с созданием фреймворка, где вьюхи могли с удобством сочитать в себе функции контроллеров. Другим экспериментом было использование исключительно иерархической событийной модели для объектов находящихся в DOM.
Даже простые вьюшки получаются очень здоровыми, имеет смысл рассматривать любые решения, которые это изменят.
Спасибо за статью, сейчас мало информации о дизайне приложений на backbone, и она очень ценная.

Честно говоря, мне немного подвывихнул мозг способ хранения/получения моделей и коллекций между контроллерами и приложением. Нет ли путей для упрощения подобный схемы?
Честно говоря, мне немного подвывихнул мозг способ хранения/получения моделей и коллекций между контроллерами и приложением. Нет ли путей для упрощения подобный схемы?

Не совсем понял, в чём сложность? Модели и коллекции хранятся и создаются приложением. Контроллер просто вызывает функцию-делегат и всё. Или я что-то не понял? :)
а зачем в контроллере объявлены
views: {}, models: {}, collections: {},
и действительно ли необходима такая большая пачка делегатов? (хотя она и положительно сказывается на инкапсуляции)
а зачем в контроллере объявлены views: {}, models: {}, collections: {},
для того, чтобы при объявлении контроллера не приходилось лезть в application. таким образом добавление модели или коллекции будет осуществляться в том месте, где это действительно нужно, без лишних телодвижений.
Получился еще один велосипед.

Backbone — это скорее MTV, чем MVC, и превращать его в MVC лично я не вижу никакого смысла.
Вы просто пытаетесь подменить понятия.

Если воспринять Router как Application, View как Controller, Template как View, то все станосится на свои места.

Я считаю, что это все просто не нужно — для небольших приложений достаточно иерархии Router (Application) -> Modules (view + list view + model + template) x n.
Для больших приложений есть 3 варианта:

* Marionette (https://github.com/derickbailey/backbone.marionette) — реализует все что вам нужно + еще кучу всего + коммунити
* Aura (https://github.com/addyosmani/aura) — для виджет-ориентированных приложений
* Использовать аккуратно Router (Application) -> Modules ( (view + list view + model + template) x n раз ) + require.js для AMD

Поверьте, этого достаточно.

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

Если кратко, то ваш контроллер делает:
1) вводит свой менеджер событий, причём не следуя конвенциям и бекбона, и джейквери, и многих других современных библиотек, — addListeners и fireEvent вместо лаконичных on и trigger.
2) завуалированно и в особо извращённой форме хранит глобальные объекты, доступные в единственном экземпляре
this.application.getController('Viewport').getView('Canvas').

От подобного делегирования меньшей связанности не будет, наоборот оно лишь поощряет использования глобальных объектов.
3) создаёт объекты через строковые литералы для геттеров из пункта 2. и ещё, как я понимаю, чтобы передать параметры в конструктор, придётся создавалку переопределять.

С пунктом 1 отлично справляется view, который будет сверху всех остальных, который будет содержать в себе прочие view. А пункты 2 и 3 вовсе вредны.
Про контроллеры бекбона выше верно написали, их в прошлом выпилили потому, что всё, кроме взаимодействия с урлами, дублирует логику Backbone.View

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

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

Вот чего в действительности не хватает бекбону, это:
1) более мощного роутера, чтобы можно было задавать опциональные параметры урлам и накладывать ограничения на содержимое параметров.
2) из коробки механизма отношений сежду моделями и коллекциями, подобно тому как в backbone.relational плагине сделано(только там реализация не самая лучшая).
3) из коробки механизма рендеринга партиалов
2) завуалированно и в особо извращённой форме хранит глобальные объекты, доступные в единственном экземпляре
тут определённые сложности, да )

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

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

а так да, велосипед-велосипедом.
Зачем свой велосипед для этого???
EventBus = { ... }


У Backbone есть своё отличное решение backbonejs.org/#Events
EventBus = { };
_.extend(EventBus, Backbone.Events);
Потому что, событие не так просто отследить, если добавлять его в лоб через Backbone.Event.on
Для того, чтобы понять, какой хендлер вызвать, нужно знать
1. Какой контроллер подписан
2. Какой вью генерирует событие
3. Какой именно хендлер нужно вызвать
Поэтому пул событий достаточно сложный, простой подписки через Backbone.Event.on оказалось недостаточно
Мне не нравится.

Размазывать логику по многочисленным views очень не хотелось

Логика должна быть в моделях. Или это не MVC.

Так же требуется возможность создавать компоненты (views) и иметь возможность слушать их события

События надо слушать у моделей. Или это не MVC.

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

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

Ох… Вы совершенно неправы…
За бизнес-логику в контроллерах надо бить по рукам.

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

blog.astrumfutura.com/2008/12/the-m-in-mvc-why-models-are-misunderstood-and-unappreciated/
www.littlehart.net/atthekeyboard/2007/04/27/fat-models-skinny-controllers/
www.bennadel.com/blog/2379-A-Better-Understanding-Of-MVC-Model-View-Controller-Thanks-To-Steven-Neiland.htm
msdn.microsoft.com/en-us/library/ff649643.aspx
www.yiiframework.com/doc/guide/1.1/en/basics.best-practices
odetocode.com/Blogs/scott/archive/2009/04/06/putting-the-m-in-mvc-part-iii.aspx
gayleforce.wordpress.com/2009/11/28/model-view-controller-mvc-where-do-you-put-your-business-logic/
stackoverflow.com/questions/235233/asp-net-mvc-should-business-logic-exist-in-controllers
stackoverflow.com/questions/212027/where-are-the-business-rules-in-mvc

Из гибкого backbone вы сделали фреймворк для монолитных, тяжело изменяющихся приложений.

Обоснуете?

Вам никогда не приходилось выносить часть интерфейска как одтельное модельное окно? или использовать готовый кусок интерфейса в другом интерфейсе?

Представления backbone прекрасны, потому что они говорят «я рисуюсь и делаю то-то». И не важно куда вставили это представление. Ему дают модель, и оно с ней работает. Такое представление может быть частью другого, и ничего об этом не знать.

У вас же есть контроллер который за всеми следит, и если вам нужно будет часть интерфейса в другом месте, вы будете дублировать этот код в другом контроллере.
Вообще, моё решение не навязывает какой-то определённый подход. Я всего лишь добавил недостающую сущность, которая позволит разгрузить View от избыточной логики, которую можно переложить на контролеры.
А какую логику в представлении вы считаете избыточной? Если можно с примером.
Не считая бизнес-логики естественно (с ней и так все ясно)
Например, в том же ToDo роль контролера выполнял главный view, он слушал события и принимал решения. При наличии контролера, так делать не обязательно, пусть контролер думает. Минус один жирный вью, остальные могут быть более атомарными, ещё в плюсах простой контролер.
Более сложный пример может быть связан с получением целого набора данных. Например, пользователь перешёл в некий раздел, для работы в котором нам необходимо получить данные для модели, с которой будет работать пользователь, потом загрузить пару дополнительных словарей. Я бы всю эту логику держал бы в контролере. Рендерим блок, показываем индикатор загрузки (можно заблокировать работу оверлеем), делаем серию запросов и по результатам передаём данные внутрь view и начинам работу. Таким образом вью не разруливает загрузку, а только получает на вход сеты данных. Это значит, что мы можем использовать компонент где угодно и сколько угодно раз, просто создавая его и передавая сеты данных, которые ему нужны для работы.
Если такая подгрузка является типичной (те разные контроллеры могут потребовать эти действия, а отличатся будут только параметрами), то есть смысл создать отдельный хелпер (библиотеку, да как угодно) и делать вызовы из контроллера

Data.Helper.loadData(itemId, callback)
За бизнес-логику в контроллерах надо бить по рукам.
Пожалуй соглашусь.

Вам никогда не приходилось выносить часть интерфейска как одтельное модельное окно? или использовать готовый кусок интерфейса в другом интерфейсе?
Приходилось и всегда без особых проблем.

У вас же есть контроллер который за всеми следит, и если вам нужно будет часть интерфейса в другом месте, вы будете дублировать этот код в другом контроллере.
У меня контролер слушает и направляет. Его цель — обеспечить функционал более высокого уровня, нежели у вью. Вью пусть работает с моделью, обновляется и тд. Как только результат этой работы становится критичным для остального приложения — оповещаем контролер и он уже решает что делать дальше. Примерно такая была идея.
Sign up to leave a comment.

Articles