Как стать автором
Обновить

Комментарии 15

Помимо вышеуказаных плюсов: легкость в тестировании. Из-за того, что модули связаны только событиями, для их тестирования достаточно тригеррить нужные события с нужными данными, без зависимостей от работы сторонних модулей
Да, насчет тестирования это я упустил. Спасибо!
Фактически приходим к истокам. Событийная модель, как известно, используется во всех фреймворках для написания GUI desktop-приложений, будь то qt, wxWidgets, vcl… Теперь с усложнением веба и переходом от «веб-сайтов» до «веб-приложений» эта модель прекрасно себя чувствует и в разработке веб-фронтендов.
Но писать событийную модель на JQ — это еще то извращение. Это полностью искажает весь смыл и логику JQ — сначала находим объект, с которым будем работать, потом работаем с каждым из них. Я уже как 4 года пользуюсь своей поделкой, которая построена только на event-based модели, и скажу вам, что это небо и земля. Мыслить событиями гораздо удобнее, чем мыслить функциями. Да и повторное использование кода колоссальное.
Что-то я не помню, чтобы я что-то говорил о JQuery )))

Да лално… В защиту подхода автора: 4 года назад в jquery еще не было deferred'ов (да что там, jquery только-только появился тогда), они вообще только недавно появились, а вот эти вот объекты отложенного выполнения как раз хорошо решают проблему построения event-based модели.
;) Я в рамках статьи говорил.
Использую такую же модель, только не в файловом менеджере, а в похожей схеме. И вот мне интересно, возникла ли у вас проблема зацикливания событий и, если да, какой вариант её решения вы выбрали? Опишу на примере: есть блок с деревом папок и есть блок с иконками папок и файлов. Если открывать папку в одном из блоков, то тот генерирует событие «открыть папку», которое приходит во второй блок, а тот открывает папку в себе и, если нет специального условия, может сгенерировать такое же событие от себя — это и приведёт к «зацикливанию». У вас есть «специальное условие» (разделение обработчиков действий пользователей и реакции на события) или какая-то другая обработка?
У нас немного другая схема не так, как вы описали. Когда происходит клик по файлу (неважно где) вид поднимает событие клик, по которому ядро обращается к серверу. И собственно событие «open» им же и вызывается, когда получены корректные данные. Так, что ваш пример у нас просто невозможен.
Хотя в теории возможна ситуация зацикливания — в обработчике события вызываем другое событие, а в его обработчике снова первое событие. Наверно абсолютного способа избежать этого — нету. Это скорее вопрос конкретной реализации.
Наверно стоит отметить это, как еще один недостаток метода.
По поводу разделения. Оно у нас есть, хотя и не в том смысле, как вы спрашиваете. Можно говорить о разных уровнях приложения где эта модель применяется. То, что я описал в примере можно считать «главным циклом» приложения — основная его логика и взаимодействие с пользователем. Кроме него есть еще «внутренние» слои приложения — например взаимодействие интерфейса (кнопки, контекстное меню) с командами. Что бы не «хардкодить» кнопки в самих командах, они у нас являются отдельными объектами и подписываются на событие «изменение» в командах.
Наверно в статье я допустил неточность — объектов, принимающих подписку может быть любое количество
Частично решить проблему генерации событий недоверенным кодом можно привязав observable объект к нашему объекту как «private» поле, выдав наружу интерфейс вида:
var observable = new Observable();
this.onReady = function(callback){
    observable.bind('ready', callback);
};


В нужном месте внутри объекта вызывается
observable.trigger('ready', {…});

Таким образом препятствуется возможность триггерить некоторые события извне.

Можно разрешить вызовы некоторых событий извне, опять же через интерфейс, который может дополнительно заведовать, что надо передать обязательно и что можно получить у вызывающей стороны
this.doSomething = function(var1, var2) {
    observable.trigger('something', {var1: var1, var2: var2, urgentDefault: 'blabla'});
};


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

В идеале, по описанной схеме, все триггеры будут выглядеть как obj.doSomething(); — либо вообще без параметров, либо с каким-то минимальным набором, который будет в этом самом методе проверен и отдан слушателям. Таким образом компонент сам внутри себя знает, что передать и как нормализовать данные. И ситуация obj.trigger('event', 'rubbish'); вообще не появится. Бинд при этом может быть какой угодно — obj.onSomething(function(var1, var2) { … }); как раз таки потому, что сам триггер спрятан.
На всякий случай уточню, что каждому модулю принадлежит ровно один observable-объект, который скрыт и с которым напрямую общается только модуль, все остальное взаимодействие идет с модулем через методы, которые он предоставляет.
Да, похоже мы друг друга не поняли:( Извиняюсь
Советую посмотреть на библиотеку js-signals, предназначенную как раз для работы с событиями (подпиской на них и вызова).
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории