Подія є повідомленням , що описує виникнення недавнього минулого.
Типова реалізація системи, керованої подіями, використовує функції диспетчера подій та обробника подій (або передплатників ). Диспетчер надає API для підключення обробників до подій (jQuery's bind
) та метод публікації події своїм підписникам ( trigger
у jQuery). Коли ви говорите про події IO або UI, зазвичай також існує цикл подій , який виявляє нові події, такі як клацання мишкою та передає їх диспетчеру. У JS-land диспетчер та цикл подій надаються браузером.
Що стосується коду, який взаємодіє безпосередньо з користувачем - реагуючи на натискання клавіш і клацання - програмування, орієнтоване на події (або його різновиди, такі як функціональне реактивне програмування ) майже неминуче. Ви, програміст, не знаєте, коли або де користувач збирається натиснути, тому вниз або в рамках графічного інтерфейсу, або в браузері, виявити дії користувача в його циклі подій та повідомити про свій код. Цей тип інфраструктури також використовується в мережевих додатках (див. NodeJS).
Ваш приклад, в якому ви піднімаєте подію у своєму коді, а не викликаєте функцію безпосередньо, має ще кілька цікавих компромісів, про які я розповім нижче. Основна відмінність полягає в тому, що видавець події ( makeItSnow
) не вказує приймача виклику; що підключено в іншому місці (у заклику до bind
вашого прикладу). Це називається " забути і забути" : makeItSnow
сповіщає світові про те, що йде сніг, але байдуже, хто слухає, що буде далі або коли це станеться - він просто передає повідомлення і пиляє з рук.
Тож підхід, керований подією, відокремлює відправника повідомлення від одержувача. Однією з переваг, яку це надає вам, є те, що дана подія може мати декілька обробників. Ви можете прив’язати gritRoads
функцію до своєї снігової події, не впливаючи на існуючий shovelSnow
обробник. У вас є гнучкість у способі підключення вашої програми; Щоб вимкнути поведінку, потрібно просто зняти bind
виклик, а не піти на полювання за кодом, щоб знайти всі випадки поведінки.
Ще одна перевага програмування, орієнтованого на події, полягає в тому, що він дає змогу десь поставити наскрізні проблеми. Диспетчер подій відіграє роль Посередника , а деякі бібліотеки (наприклад, Brighter ) використовують конвеєр, щоб ви могли легко підключати загальні вимоги, такі як реєстрація або якість обслуговування.
Повне розкриття інформації: Яскравіший розробляється в компанії Huddle, де я працюю.
Третя перевага розв'язки відправника події від приймача є те , що вона дає вам гнучкість в коли ви обробляти подія. Ви можете обробити кожен тип подій у власному потоці (якщо ваш диспетчер подій підтримує його), або ви можете помістити підняті події на брокера повідомлень, наприклад RabbitMQ, і обробити їх асинхронним процесом або навіть обробити їх масово протягом ночі. Одержувач події може перебувати в окремому процесі або на окремій машині. Вам не потрібно змінювати код, який викликає подію для цього! Це велика ідея архітектури "мікросервісних": автономні сервіси спілкуються за допомогою подій, а посередництво програми обміну повідомленнями є основою програми.
Для досить іншого прикладу стилю, керованого подіями, зверніться до дизайну, керованого доменом , де події домену використовуються, щоб допомогти зберегти агрегати окремими. Наприклад, розглянемо Інтернет-магазин, який рекомендує товари на основі історії ваших покупки. Customer
Повинен мати свою історію покупок оновлюється , коли ShoppingCart
оплачується. ShoppingCart
Агрегат може повідомити Customer
, піднявши CheckoutCompleted
подія; Customer
буде оновлюватися в окремій транзакції у відповідь на подію.
Основним недоліком цієї моделі, керованої подіями, є непрямість. Зараз важче знайти код, який обробляє подію, оскільки ви не можете просто перейти до нього за допомогою свого IDE; ви повинні з'ясувати, де подія пов'язана в конфігурації, і сподіватися, що ви знайшли всіх обробників. Є більше речей, які потрібно тримати в голові в будь-який час. Тут можуть допомогти умови стилів коду (наприклад, розміщення всіх дзвінків bind
в одному файлі). Заради вашого розуму важливо використовувати лише один диспетчер подій і послідовно використовувати його.
Ще одним недоліком є те, що важко відремонтувати події. Якщо вам потрібно змінити формат події, вам також потрібно змінити всі приймачі. Це посилюється, коли передплатники події знаходяться на різних машинах, адже тепер вам потрібно синхронізувати версії програм!
За певних обставин результативність може викликати занепокоєння. Під час обробки повідомлення диспетчер повинен:
- Знайдіть правильні обробники в деякій структурі даних.
- Побудуйте конвеєр обробки повідомлень для кожного обробника. Це може включати купу розподілу пам'яті.
- Динамічно викликайте обробників (можливо, використовуючи роздуми, якщо мова цього вимагає).
Це, звичайно, повільніше, ніж звичайний виклик функції, який передбачає лише натискання нового кадру на стек. Однак гнучкість, яку надає вам орієнтована на події архітектура, значно полегшує ізоляцію та оптимізацію повільного коду. Наявність можливості подати роботу в асинхронний процесор - це велика виграш, оскільки це дозволяє негайно обслуговувати запит, коли важку роботу вирішують у фоновому режимі. У будь-якому випадку, якщо ви взаємодієте з БД або малюєте речі на екрані, то витрати на IO повністю перекриють витрати на обробку повідомлення. Це уникнення передчасної оптимізації.
Підводячи підсумок, події - це чудовий спосіб побудувати програмне забезпечення, що не поєднується, але вони не обійдуться. Наприклад, було б помилкою замінити кожен виклик функції у вашій програмі подією. Використовуйте події для створення значущих архітектурних поділів.
$(document).bind('snow', shovelShow)
. Не потрібно загортати його в анонімну функцію.