Програмування на основі подій: коли воно того варто?


19

Гаразд, я знаю, що заголовок цього питання майже ідентичний " Коли я повинен використовувати програмування на основі подій?" але відповіді на вказане питання не допомогли мені вирішити, чи слід використовувати події в конкретному випадку, з яким я стикаюся.

Я розробляю невеликий додаток. Це простий додаток, і здебільшого його функціональність - це базовий CRUD.

Після певних подій (при зміні певних даних) програма повинна записати локальну копію цих даних у файл. Я не впевнений, який найкращий спосіб здійснити це. Я можу:

  • Події пожежі, коли дані модифікуються, і зв'язують відповідь (створюють файл) на такі події. Як варіант, реалізуйте схему спостерігачів. Це здається зайвою складністю.
  • Виклик коду, що генерує файл, безпосередньо з коду, що модифікує дані. Набагато простіше, але здається неправильним, що залежність повинна бути такою, тобто здається неправильним, що основна функціональність програми (код, що модифікує дані) повинна бути поєднана з додатковою перевагою (кодом, який генерує резервний файл). Я знаю, однак, що ця програма не розвиватиметься до того моменту, коли ця сполука створює проблему.

Який найкращий підхід у цьому випадку?


2
Я б сказав, що не реалізуйте нічого самостійно - просто використовуйте існуючу шину подій. Це зробить життя набагато простішим ...
Борис Павук

Програмування на основі подій по своїй суті є асинхронним. Події можуть відбуватися або не відбуватися в порядку, який ви задумали, або, можливо, в іншому порядку або взагалі. Якщо ви можете впоратися з цією додатковою складністю, продовжуйте це робити.
Пітер Б

Зазвичай, що керується подіями, означає, що ваш код надається як зворотній дзвінок, і вони викликаються з інших місць способами, які ви не можете передбачити. Ваш опис більше звучить так, коли у вашому коді трапляється щось конкретне, вам потрібно зробити більше, ніж вимагатиме наївна реалізація. Просто введіть додаткові дзвінки.
Thorbjørn Ravn Andersen

Там є різниця між подією , керованим і на основі подій. Ознайомтеся з прикладом високоефективного епізоду 355 подкаста .NET Rocks з Тедом Файсоном, Тед Файсон приймає події до кінця! ( пряма URL-адреса для завантаження ) та книжкове програмування на основі подій: обмеження подій .
Пітер Мортенсен

Інтерв'ю з Тедом Файсоном починається о 13 хв 10 сек.
Пітер Мортенсен

Відповіді:


31

Дотримуйтесь принципу KISS: Тримайте це просто, тупо або принцип YAGNI: Вам цього не потрібно.

Ви можете написати код на зразок:

void updateSpecialData() {
    // do the update.
    backupData();
}

Або ви можете написати код на зразок:

void updateSpecialData() {
     // do the update.
     emit SpecialDataUpdated();
}

void SpecialDataUpdatedHandler() {
     backupData();
}

void configureEventHandlers() {
     connect(SpecialDataUpdate, SpecialDataUpdatedHandler);
}

У випадку відсутності вагомих причин робити інше, дотримуйтесь більш простого маршруту. Такі методи, як обробка подій, є потужними, але вони збільшують складність вашого коду. Для роботи йому потрібно більше коду, і це ускладнює дотримання того, що відбувається у вашому коді.

Події дуже важливі в правильній ситуації (уявіть, що намагаєтеся програмувати інтерфейс користувача без подій!), Але не використовуйте їх, коли натомість ви можете KISS або YAGNI.


Мені особливо подобається те, що ви згадали, що стрілянина подій при зміні даних не є тривіальною.
NoChance

13

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

  • це простіше в застосуванні та підтримці, ніж повний код, керований подіями.
  • зв'язок між суб'єктом і спостерігачем може бути абстрактним, що полегшує розмежування проблем.
  • ідеально підходить для відношення один до багатьох (суб'єкти мають одного або багатьох спостерігачів).

Підхід, орієнтований на події, варто інвестувати у складніші сценарії, коли може відбуватися багато різних взаємодій, у контексті багатьох до багатьох, або якщо передбачаються ланцюгові реакції (наприклад, суб'єкт інформує спостерігача, який у деяких випадках хоче змінити предмет чи інші предмети)


1
Я розгублений, чи не спостерігач лише один із способів реалізації подій?
svick

1
@svick Я так не думаю. У програмуванні на основі подій у вас є головний цикл, який обробляє події у взаємозв'язку багато-багато, з роз'єднаними відправляючими та спостерігачами. Я думаю, що спостерігач може зробити свій внесок, обробляючи пертикулярний тип події, але ви не можете досягти повного спектру ППД лише за допомогою спостерігача. Я думаю, що плутанина походить від того, що в програмному забезпеченні, що керується подіями, іноді спостерігачі реалізуються на вершині обробки подій (як правило, MVC з графічним інтерфейсом)
Крістоф

5

Як ви кажете, події є чудовим інструментом для зменшення зв’язку між класами; тому, хоча це може включати написання додаткового коду на деяких мовах без вбудованої підтримки подій, це зменшує складність великої картини.

Події, мабуть, є одним із найважливіших інструментів ОО (За словами Алана Кей - Об'єкти спілкуються, надсилаючи та отримуючи повідомлення ). Якщо ви використовуєте мову, яка має вбудовану підтримку подій, або розглядає функції як першокласних громадян, то використання їх не є розумом.

Навіть у мовах без вбудованої підтримки кількість шаблонів для щось подібне до шаблону Observer досить мінімальне. Можливо, ви зможете десь знайти гідну загальну бібліотеку подій, яку ви можете використовувати у всіх своїх програмах, щоб мінімізувати котельну табличку. (Загальний агрегатор подій або посередник подій корисний майже в будь-якому застосуванні).

Чи варто в невеликому додатку? Я б точно сказав, що так .

  • Збереження класів, з'єднаних один з одним, забезпечує чистоту графіка залежності вашого класу.
  • Класи без будь-яких конкретних залежностей можна перевірити ізольовано, не враховуючи інших класів тестів.
  • Класи без конкретних залежностей вимагають меншої кількості опробованих тестів для повного висвітлення.

Якщо ви думаєте: "О, але це дійсно лише дуже маленьке додаток, це насправді не так важливо" , подумайте:

  • Малі програми іноді в кінцевому підсумку поєднуються з більшими додатками.
  • Невеликі програми, ймовірно, включають принаймні деяку логіку або компоненти, які згодом можуть знадобитися повторно використовувати в інших програмах.
  • Вимоги до невеликих додатків можуть змінюватися, що спонукає до необхідності рефакторації, що простіше, коли існуючий код роз’єднується.
  • Додаткові функції можуть бути додані пізніше, що спонукає до необхідності розширення існуючого коду, що також набагато простіше, коли існуючий код уже роз'єднаний.
  • Захватний код, як правило, не потребує більше часу, ніж щільно зв'язаний код; але щільно пов'язаний код займає рефактор і тестування набагато більше часу, ніж слабко пов'язаний код.

В цілому, розмір програми не повинен бути вирішальним фактором, чи слід тримати заняття вільно поєднаними; Принципи SOLID не тільки для великих програм, вони застосовні до програмного забезпечення та кодових баз у будь-якому масштабі.

Насправді, заощаджений час в одиниці тестування ваших слабко зв'язаних класів в ізоляції повинен протирівноважувати будь-який додатковий витрачений час на розв'язку цих класів.


2

Шаблон спостерігачів може бути реалізований набагато меншим способом, ніж описується у статті Вікіпедії (або в книзі GOF), якщо ваші мови програмування підтримують щось на кшталт "зворотного виклику" або "делегатів". Просто перенесіть метод зворотного виклику у свій CRUD-код (метод спостерігача, який може бути або загальним методом «запис у файл», або порожнім). Замість "запуску події" просто зателефонуйте до цього зворотного дзвінка.

Отриманий код буде лише мінімально складнішим, ніж виклик коду, що генерує файли безпосередньо, але без недоліків тісного з’єднання непов'язаних компонентів.

Це принесе вам "найкраще з обох світів", не жертвуючи розв'язкою для "ЯГНІ".


Це працює вперше Doc, але коли подія потребує запуску другої речі, то, ймовірно, клас потрібно буде модифікувати, роблячи це таким чином. Якщо ви використовуєте шаблон спостерігача, ви можете додати стільки нових способів поведінки, скільки хотіли, не відкриваючи оригінальний клас резервного копіювання для модифікації.
RubberDuck

2
@RubberDuck: ОП шукала рішення "уникнути зайвої складності" - якщо потрібні різні події / різні форми поведінки, він, мабуть, не вважатиме модель спостерігача занадто складною. Тож я погоджуюся на те, що ви сказали, коли справи стають складнішими, повноцінний спостерігач служив би йому краще, але лише тоді.
Док Браун

Справедлива заява, але мені здається, що це розбите вікно.
RubberDuck

2
@RubberDuck: додавання повноцінного спостерігача з механікою видавця / підписки «на всякий випадок», коли це не дуже потрібно, мені здається, що переобладнання - це не краще.
Док Браун

1
Я не погоджуюся, що це може бути над інженером. Я, мабуть, відчуваю так, як це роблю, тому що це банально реалізувати у своїй вибірці. У будь-якому випадку ми просто погодимось не погодитися?
RubberDuck
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.