Для чого слід використовувати плагіни: гачки, події чи щось інше?


24

Розглянемо додаток, який дозволяє плагінам реагувати на його програмний потік.

Я знаю 2 способи досягти цього: гачки та події

1. Гачки

Використовуйте дзвінки для порожніх функцій всередині основного потоку програми. Ці функції можуть бути замінені плагінами.

Наприклад, Drupal CMS реалізує гачки, доступні для модулів та тем. Ось приклад того, як гак реалізований у функції file_copy .

function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
    // ... [File copying routine]

    // Inform modules that the file has been copied.
    module_invoke_all('file_copy', $file, $source);

    return $file;
    // ...
}

Модуль може реалізувати modulename_file_copy($file, $source)функцію , яка буде викликатися в module_invoke_allін file_copy. Після закінчення цієї функції file_copyзапуск буде відновлено.

2. Події

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

Наприклад, плагін галереї jQuery Fotorama реалізує кілька подій . Як приклад, ось частина його showметоду, який розпалює fotorama:showподію.

  that.show = function (options) {
    // ... [show the new frame]

    // [fire the event]
    options.reset || triggerEvent('show', {
      user: options.user,
      time: time
    });

    // ... [do lots of other stuff with navigation bars, etc.]
  };

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

$('.fotorama').on(
  'fotorama:show',
  function (e, fotorama, extra) {
    console.log(e.type + (extra.user ? ' after user’s touch' : ''));
    console.log('transition duration: ' + extra.time);
  }
);

ПИТАННЯ

  1. Чи існують інші основні способи реалізації такої поведінки плагінів?

  2. Якщо ні, то коли слід використовувати гачки, а коли слід використовувати події? Враховуючи кінцеву мету - зробити код більш корисним і читабешим, як з точки зору програми, так і з точки зору розробника плагінів?

Відповіді:


17

Основна відмінність між гачком і подією - це вільна муфта від жорсткої муфти.

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

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

Вони обидва досягають однакових результатів. Це просто залежить від того, як ви хочете з'єднати плагін із додатком.

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

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

Ви попросили альтернативних підходів.

Команди:

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

Макроси:

Замість плагінів реагують на те, коли все відбувається. Плагіни активно спричиняють щось. Макрос - це невелика мова високого рівня, що працює над програмою, яка говорить їй, що робити.

Державні слухачі змін:

Події ініціюються програмою заздалегідь продуманою розробником. Розробник повинен свідомо написати код, який видає подію. Натомість, альтернативний підхід полягає в тому, щоб об'єкти автоматично транслювались, коли змінився їх внутрішній стан. Або зміна властивості, або інші показники. Потім плагіни можуть прослуховувати ці конкретні зміни стану і відповідно реагувати. Перевага такого підходу полягає в тому, що програмісту не потрібно пам'ятати, щоб транслювати події. Наприклад, може бути об’єкт Document, і програміст встановлює прапор, який позначає, що документ потрібно зберегти. Ця зміна стану транслюється на прослуховування плагінів, і там може бути плагін, який змінює назву документа на зірочку.


2
+1 для альтернатив, -1 для визначення і зчіпного аргументу (який робить існує , але зчеплення є наслідком конструктивних варіантів, в залежності від того назви ви даєте вашу систему плагін)

5
Я думаю, ви також робите припущення щодо того, як подія подорожує від генератора до спостерігача / слухача. Насправді це навпаки, гачки щільно з'єднані, тоді як події - ні.
Ахмед Масуд

3

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

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

Візьміть наступний приклад з гачками: у вас є система, де працює 20 плагінів. Один із цих плагінів називає file_copyметод таким чином, як це задокументовано, і очікує, що результат буде задокументований. Але якийсь інший плагін підключив цю функцію, і тому одне з наступних питань спричиняє збій або несправність:

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

Якщо ви зробите те саме, що вище, з подіями з тими ж проблемами всередині цих плагінів, відбувається таке:

  • Функція події плагіна X виходить з ладу, але всі інші працюють нормально. Але оскільки ці плагіни не пов’язані між собою, ви можете просто вимкнути цей збій, а інші продовжують працювати нормально.
  • Дивна інформація може бути належним чином оброблена вашою функцією, і ви можете правильно перевірити всі можливі речі для кожного плагіна окремо. Зараз у розробника плагінів є стабільний і надійний спосіб фактичного тестування свого плагіна, що дозволяє йому бути впевненим, що якщо він працює для нього, він буде працювати для всіх. Якщо один плагін забезпечує неправильний вхід, його можна виділити до цього плагіна.
  • Так само результат можна перевірити та визначити належним чином за будь-яких обставин, тому розробник плагінів має стабільну та надійну відповідь від цієї функції, яку він / вона може перевірити.

1

Спадщина може бути варіантом.

Окрім гаків, для успадкування не потрібні додаткові визначення методів, і немає втрати продуктивності для виклику порожнього методу у випадку, якщо нічого не підключено.

Крім подій, для успадкування також не потрібен додатковий код для виклику події.

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


-1 Тому що ви використовуєте "Наслідування", а потім змінюєте код інстанції, щоб використовувати свою специфікацію та неправомірно успадковувати, оскільки нова поведінка має інше призначення як основне додаток ...
SparK

0

Однозначно події. Це дозволяє вашій архітектурі бути масштабнішою.

Уявіть, що буде, якщо вам потрібно буде, наприклад, помістити свій плагін на окрему машину. Використання подій - вам потрібно просто змінити невеликий код коду, щоб зробити свою подію мережевою.

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