ݺߣ

ݺߣShare a Scribd company logo
Антон Веретенников
Илья Семаков
«ПЕРЕХОД ОТ КОЛЛБЕКОВ
К СОБЫТИЯМ»
Public API
Frontend Backend
AJAX
разработать frontend-часть
для нового проекта заказчика
Задача:
Search
Results
Filter #1
1 2 ... N
Filter #2
разработать frontend-часть
для нового проекта заказчика
Задача:
Frontend
Filter #3
Combobox
Sort
Checkbox
Checkbox
Checkbox
Checkbox
Title
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
nonummy nibh euismod tincidunt ut laoreet dolore
Checkbox
Checkbox
Combobox
Checkbox
Checkbox
Checkbox
Checkbox
Checkbox
Checkbox
разработать frontend-часть
для нового проекта заказчика
Задача:
Пути решения
Callback
разработать frontend-часть
для нового проекта заказчика
Задача:
Event-driven
Пути решения
разработать frontend-часть
для нового проекта заказчика
Задача:
Callback Event-driven
?
Пути решения
Component_1 = { 
update : function( callback ) { callback() },
  reset : function( callback ){ callback() }
};
Component_2 = {
  business : function(){
   Component_1.update(this.callback);
  },
  callback : function(){ ... }
};
Callback
Сначала все выглядит вот так
Component_1 = { 
update : function( callback ) { callback() },
 reset : function( callback ){ callback() }
};
Component_2 = {
  business : function(){
   Component_1.update(this.callback);
  },
  callback : function(){ ... }
};
Component_3 = {
  business : function(){
   Component_1.reset(this.callback);
  },
  callback : function(){ ... }
};
Callback
Появляются новые требования
Component_1 = { 
update : function( callback ) { callback() },
  reset : function( callback ){ callback() }
};
Component_2 = {
  business : function(){
    Component_1.update(this.callback);
  },
  callback : function(){ ... }
};
Component_3 = {
  business : function(){
    Component_1.reset(this.callback);
  },
  callback : function(){ ... }
};
Component_4 = {
  business : function(){
    Component_2.business();
  }
};
Callback
... и ещё
Callback
... а в итоге получаем
Callback
Хорошо работают на несложных проектах.—
— Слабая гибкость из-за постоянно
возрастающих зависимостей.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Теория
Event-driven. Теория
Component_3 = {
  construct : function(){
    Manager.addListener('completeReset', this.callback);
  },
  business : function(){
    Manager.fireEvent('needReset');
  },
  callback : function(){ ... }
};
Component_4 = {
  business : function(){
    Manager.fireEvent('needBusiness');
  }
};
Manager = {
  addListener : function(){ ... },
  fireEvent : function(){ ... }
};
Component_1 = {
  construct : function(){
    Manager.addListener('needUpdate', this.update);
    Manager.addListener('needReset', this.reset);
  },
  update : function(){
    Manager.fireEvent('completeUpdate');
  },
  reset : function(){
    Manager.fireEvent('completeReset');
  }
};
Component_2 = {
  construct : function(){
    Manager.addListener('needBusiness', this.business);
    Manager.addListener('completeUpdate', this.callback);
  },
  business : function(){
    Manager.fireEvent('needUpdate');
  },
  callback : function(){ ... }
};
С точки зрения кода
Manager — тот же Module.
В нашем случае, часть функций
менеджера выполняется jQuery.
Другая часть выполняется
одним из компонентов.
Manager «размазало» по коду :)
Но дискомофорта из-за этого не испытываем.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Вызов событий
Генерируем сразу на компоненте.
Избавились от посредников.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Шина.
Непосредственно на компоненте.
Специально созданный
объект (proxy).
RequestSender = function( elem ){
    this.$element = jQuery(elem);
    ...
  }
  RequestSender.prototype._getData = function(){
    this.$element.trigger('js-waiting-data');
  }
Вызов событий
Генерируем сразу на компоненте.
Избавились от посредников.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Проблема зоны видимости событий
Разные компоненты могут вызывать
один и тот же эвент.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
События привязаны к компонентам.
Некоторые события существуют
вне компонентов (один элемент —
один эвент — несколько компонентов).
  RequestSender = function( elem ){
    this.$element = jQuery(elem);
  }
 
  RequestSender.prototype.complete = function(){
    this.$element.trigger('js-form-update');
  }
 
  DynamicForm = function( elem ){
    this.$element = jQuery(elem);
  }
  DynamicForm.prototype.update= function(){
    this.$element.trigger('js-form-update');
  }
 
Проблема зоны
видимости событий
Разные компоненты могут вызывать
один и тот же эвент.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Проблема именования событий
Имена событий — параметризуемые.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Как быть с дефолтными событиями?
Как быть с событиями конкретных
компонентов?
Что делать с общими событиями?
  RequestSender = function( elem ){
    this.$element = jQuery(elem);
    this.requestEvent = this.$element.data('requestEvent');
    this.waitingDataEvent = this.$element.data('waitingDataEvent');
    this.readyDataEvent = this.$element.data('readyDataEvent');
  }
Проблема именования событий
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Имена события — параметризуемые.
Кто вызвал событие
на компоненте?
Источник события — параметр события.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Каждому источнику — уникальное
событие.
Передавать источник события.
  this.$element.trigger(
    this.changeEvent,
    {'eventSource' : 'filter'}
  );
Кто вызвал событие
на компоненте?
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Источник события — параметр события.
Для кого предназначено
событие?
Источник события — параметр события.
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Получатель — не всегда источник.
Каждому получателю — уникальное
событие.
Передавать получателя.
this.$element.trigger(
    this.readyEvent,
    {'eventTarget' : this.$resultList}
);
Для кого предназначено
событие?
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Источник события — параметр события.
Проблемы внутри компонента
Кто кого: метод вызывает событие
или же событие вызывает метод?
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
Событие предназначено
для связывания компонентов.
Компонент слушает сам себя.
Кто кого: метод вызывает событие
или же событие вызывает метод?
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
  this._init = function(){ 
    var context = this;
   
    this.$element.on('js-clear', function(){
      context.clearFields();
    });
  }
 
ИЛИ
 
  this.clearFields = function(){
    ...
    this.$element.trigger('js-clear');
  };
Проблемы внутри компонента
Кто кого: метод вызывает событие
или же событие вызывает метод?
Module_2
Component_3
Manager
Event
Component_4
Module_1
Component_1
Component_2
Event-driven. Практика
  this._init = function(){ 
    var context = this;
   
    this.$element.on('js-do-clear', function(){
      context.clearFields();
    });
  }
 
  this.clearFields = function(){
    ...
    this.$element.trigger('js-complete-clear');
  };
Проблемы внутри компонента
Event-driven. Итоги
Одинаково работают на любых проектах.—
—
—
—
—
—
Меньше зависимостей, больше гибкости.
Лучшая отказоустойстойчивость.
Сложность восприятия.
Большая вероятность появления «мусора».
Необходимость более тщательного
проектирования приложения.
Забыть нельзя использовать
Вопросы?
Спасибо!
Антон Веретенников
Илья Семаков

More Related Content

Антон Веретенников и Илья Семаков. Презентация

  • 2. Public API Frontend Backend AJAX разработать frontend-часть для нового проекта заказчика Задача:
  • 3. Search Results Filter #1 1 2 ... N Filter #2 разработать frontend-часть для нового проекта заказчика Задача: Frontend Filter #3 Combobox Sort Checkbox Checkbox Checkbox Checkbox Title Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore Checkbox Checkbox Combobox Checkbox Checkbox Checkbox Checkbox Checkbox Checkbox
  • 4. разработать frontend-часть для нового проекта заказчика Задача: Пути решения Callback
  • 5. разработать frontend-часть для нового проекта заказчика Задача: Event-driven Пути решения
  • 6. разработать frontend-часть для нового проекта заказчика Задача: Callback Event-driven ? Пути решения
  • 7. Component_1 = {  update : function( callback ) { callback() },   reset : function( callback ){ callback() } }; Component_2 = {   business : function(){    Component_1.update(this.callback);   },   callback : function(){ ... } }; Callback Сначала все выглядит вот так
  • 8. Component_1 = {  update : function( callback ) { callback() },  reset : function( callback ){ callback() } }; Component_2 = {   business : function(){    Component_1.update(this.callback);   },   callback : function(){ ... } }; Component_3 = {   business : function(){    Component_1.reset(this.callback);   },   callback : function(){ ... } }; Callback Появляются новые требования
  • 9. Component_1 = {  update : function( callback ) { callback() },   reset : function( callback ){ callback() } }; Component_2 = {   business : function(){     Component_1.update(this.callback);   },   callback : function(){ ... } }; Component_3 = {   business : function(){     Component_1.reset(this.callback);   },   callback : function(){ ... } }; Component_4 = {   business : function(){     Component_2.business();   } }; Callback ... и ещё
  • 10. Callback ... а в итоге получаем
  • 11. Callback Хорошо работают на несложных проектах.— — Слабая гибкость из-за постоянно возрастающих зависимостей.
  • 13. Event-driven. Теория Component_3 = {   construct : function(){     Manager.addListener('completeReset', this.callback);   },   business : function(){     Manager.fireEvent('needReset');   },   callback : function(){ ... } }; Component_4 = {   business : function(){     Manager.fireEvent('needBusiness');   } }; Manager = {   addListener : function(){ ... },   fireEvent : function(){ ... } }; Component_1 = {   construct : function(){     Manager.addListener('needUpdate', this.update);     Manager.addListener('needReset', this.reset);   },   update : function(){     Manager.fireEvent('completeUpdate');   },   reset : function(){     Manager.fireEvent('completeReset');   } }; Component_2 = {   construct : function(){     Manager.addListener('needBusiness', this.business);     Manager.addListener('completeUpdate', this.callback);   },   business : function(){     Manager.fireEvent('needUpdate');   },   callback : function(){ ... } };
  • 14. С точки зрения кода Manager — тот же Module. В нашем случае, часть функций менеджера выполняется jQuery. Другая часть выполняется одним из компонентов. Manager «размазало» по коду :) Но дискомофорта из-за этого не испытываем. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика
  • 15. Вызов событий Генерируем сразу на компоненте. Избавились от посредников. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Шина. Непосредственно на компоненте. Специально созданный объект (proxy).
  • 16. RequestSender = function( elem ){     this.$element = jQuery(elem);     ...   }   RequestSender.prototype._getData = function(){     this.$element.trigger('js-waiting-data');   } Вызов событий Генерируем сразу на компоненте. Избавились от посредников. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика
  • 17. Проблема зоны видимости событий Разные компоненты могут вызывать один и тот же эвент. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика События привязаны к компонентам. Некоторые события существуют вне компонентов (один элемент — один эвент — несколько компонентов).
  • 18.   RequestSender = function( elem ){     this.$element = jQuery(elem);   }     RequestSender.prototype.complete = function(){     this.$element.trigger('js-form-update');   }     DynamicForm = function( elem ){     this.$element = jQuery(elem);   }   DynamicForm.prototype.update= function(){     this.$element.trigger('js-form-update');   }   Проблема зоны видимости событий Разные компоненты могут вызывать один и тот же эвент. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика
  • 19. Проблема именования событий Имена событий — параметризуемые. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Как быть с дефолтными событиями? Как быть с событиями конкретных компонентов? Что делать с общими событиями?
  • 20.   RequestSender = function( elem ){     this.$element = jQuery(elem);     this.requestEvent = this.$element.data('requestEvent');     this.waitingDataEvent = this.$element.data('waitingDataEvent');     this.readyDataEvent = this.$element.data('readyDataEvent');   } Проблема именования событий Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Имена события — параметризуемые.
  • 21. Кто вызвал событие на компоненте? Источник события — параметр события. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Каждому источнику — уникальное событие. Передавать источник события.
  • 22.   this.$element.trigger(     this.changeEvent,     {'eventSource' : 'filter'}   ); Кто вызвал событие на компоненте? Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Источник события — параметр события.
  • 23. Для кого предназначено событие? Источник события — параметр события. Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Получатель — не всегда источник. Каждому получателю — уникальное событие. Передавать получателя.
  • 24. this.$element.trigger(     this.readyEvent,     {'eventTarget' : this.$resultList} ); Для кого предназначено событие? Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Источник события — параметр события.
  • 25. Проблемы внутри компонента Кто кого: метод вызывает событие или же событие вызывает метод? Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика Событие предназначено для связывания компонентов. Компонент слушает сам себя.
  • 26. Кто кого: метод вызывает событие или же событие вызывает метод? Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика   this._init = function(){      var context = this;         this.$element.on('js-clear', function(){       context.clearFields();     });   }   ИЛИ     this.clearFields = function(){     ...     this.$element.trigger('js-clear');   }; Проблемы внутри компонента
  • 27. Кто кого: метод вызывает событие или же событие вызывает метод? Module_2 Component_3 Manager Event Component_4 Module_1 Component_1 Component_2 Event-driven. Практика   this._init = function(){      var context = this;         this.$element.on('js-do-clear', function(){       context.clearFields();     });   }     this.clearFields = function(){     ...     this.$element.trigger('js-complete-clear');   }; Проблемы внутри компонента
  • 28. Event-driven. Итоги Одинаково работают на любых проектах.— — — — — — Меньше зависимостей, больше гибкости. Лучшая отказоустойстойчивость. Сложность восприятия. Большая вероятность появления «мусора». Необходимость более тщательного проектирования приложения.