У WordPress есть плагины, у jQuery есть плагины, а также у Gatsby, Eleventy и Vue.
Плагины — это общая функция библиотек и фреймворков, и на то есть веская причина: они позволяют разработчикам добавлять функциональные возможности безопасным и расширяемым способом. Это делает основной проект более ценным и создает сообщество — и все это без дополнительной нагрузки на техническое обслуживание. Здорово!
Итак, как построить подключаемую систему? Давайте ответим на этот вопрос, создав собственный плагин на JavaScript.
Давайте создадим систему плагинов
Начнем с примера проекта под названием BetaCalc. BetaCalc стремится стать минималистичным калькулятором JavaScript, к которому другие разработчики могут добавлять «кнопки». Вот некоторый базовый код для начала работы:
// 计算器
const betaCalc = {
currentValue: 0,
setValue(newValue) {
this.currentValue = newValue;
console.log(this.currentValue);
},
plus(addend) {
this.setValue(this.currentValue + addend);
},
minus(subtrahend) {
this.setValue(this.currentValue - subtrahend);
}
};
// 使用计算器
betaCalc.setValue(3); // => 3
betaCalc.plus(3); // => 6
betaCalc.minus(2); // => 4
Мы определяем калькулятор как объективную вещь, чтобы упростить задачу.console.log
Распечатайте результат для работы.
В настоящее время функциональность действительно ограничена. у нас естьsetValue
метод, который принимает число и отображает его на «экране». У нас также есть дополнение (plus
) и вычитание (minus
), который будет выполнять операцию над текущим отображаемым значением.
Теперь пришло время добавить больше функциональности. Сначала создайте систему плагинов.
Самая маленькая система плагинов в мире
Мы создадим регистрацию (register
), который другие разработчики могут использовать для регистрации плагинов в BetaCalc. Работа этого метода проста: получить внешний плагин, получить егоexec
функцию и присоединяем ее к нашему калькулятору как новый метод:
// 计算器
const betaCalc = {
// ...其他计算器代码在这里
register(plugin) {
const { name, exec } = plugin;
this[name] = exec;
}
};
Вот пример плагина, который предоставляет "квадратный (squared
)" кнопка:
// 定义插件
const squaredPlugin = {
name: 'squared',
exec: function() {
this.setValue(this.currentValue * this.currentValue)
}
};
// 注册插件
betaCalc.register(squaredPlugin);
Во многих системах плагинов плагины обычно делятся на две части:
- код для выполнения
- Метаданные (такие как имя, описание, номер версии, зависимости и т. д.)
В нашем плагинеexec
функция содержит наш код,name
это наши метаданные. После регистрации плагинаexec
Функция будет прикреплена как метод непосредственно к нашемуbetaCalc
объект, тем самым давая доступ к BetaCalc'sthis
.
В BetaCalc теперь есть новая «квадратная» кнопка, которую можно вызвать напрямую:
betaCalc.setValue(3); // => 3
betaCalc.plus(2); // => 5
betaCalc.squared(); // => 25
betaCalc.squared(); // => 625
Эта система имеет много преимуществ. Плагин — это простой литерал объекта, который можно передать нашей функции. Это означает, что плагины можно загружать через npm и импортировать как модули ES6. Простота распространения очень важна!
Но у нашей системы есть недостатки.
Предоставляет доступ к BetaCalc через плагиныthis
разрешения, они имеют доступ для чтения/записи ко всему коду BetaCalc. Пока это работает для получения и установкиcurrentValue
Полезно, но и опасно. Если плагин хочет переопределить внутренние функции (например,setValue
), это может привести к неожиданным результатам для BetaCalc и других подключаемых модулей. Это нарушает принцип открытого-закрытого, согласно которому программный объект должен быть открыт для расширения, но закрыт для модификации.
Кроме того, функция «квадрат» работает, производя побочные эффекты. Это не редкость в JavaScript, но это не очень хорошо, особенно когда другие плагины могут находиться в том же внутреннем состоянии. Более практичный подход поможет сделать наши системы более безопасными и предсказуемыми.
Улучшенная архитектура плагина
Давайте еще раз взглянем на лучшую архитектуру плагина. В следующем примере изменяются как калькулятор, так и его подключаемый API:
// 计算器
const betaCalc = {
currentValue: 0,
setValue(value) {
this.currentValue = value;
console.log(this.currentValue);
},
core: {
'plus': (currentVal, addend) => currentVal + addend,
'minus': (currentVal, subtrahend) => currentVal - subtrahend
},
plugins: {},
press(buttonName, newVal) {
const func = this.core[buttonName] || this.plugins[buttonName];
this.setValue(func(this.currentValue, newVal));
},
register(plugin) {
const { name, exec } = plugin;
this.plugins[name] = exec;
}
};
// 我们得插件,平方插件
const squaredPlugin = {
name: 'squared',
exec: function(currentValue) {
return currentValue * currentValue;
}
};
betaCalc.register(squaredPlugin);
// 使用计算器
betaCalc.setValue(3); // => 3
betaCalc.press('plus', 2); // => 5
betaCalc.press('squared'); // => 25
betaCalc.press('squared'); // => 625
Здесь мы внесли некоторые заметные изменения.
Во-первых, мы отделяем плагин от «основных» методов калькулятора (таких как «плюс» и «минус»), помещая его в отдельный объект плагина. Храните наши плагины вplugins
объект может сделать нашу систему более безопасной. Плагины, обращающиеся к этим плагинам, теперь не будут видеть свойства BetaCalc, а толькоbetaCalc.plugins
характеристики.
Во-вторых, мы внедрилиpress
метод, который ищет функцию кнопки по имени и вызывает ее. Теперь, когда мы вызываем плагинexec
мы конвертируем текущее значение калькулятора (currentValue
) в функцию и ожидать, что она вернет новое значение калькулятора.
По существу, это новоеpress
метод преобразует все кнопки нашего калькулятора в чистые функции. Они принимают значение, выполняют действие и возвращают результат. Это имеет много преимуществ:
- Это упрощает API.
- Это упрощает тестирование (для BetaCalc и самого плагина).
- Это уменьшает зависимости нашей системы и делает ее более слабо связанной.
Эта новая архитектура более ограничена, чем первый пример, но работает хорошо. По сути, мы устанавливаем барьеры для авторов плагинов, ограничивая их только теми изменениями, которые мы хотим, чтобы они вносили.
На самом деле, это может быть слишком строго! Теперь наш плагин-калькулятор может толькоcurrentValue
работать. Если авторы плагинов хотят добавить дополнительные функции (например, кнопку «запомнить» или способ отслеживать историю), они мало что могут сделать.
Может быть, это хорошо. Сила, которую вы даете авторам плагинов, представляет собой тонкий баланс. Предоставление им слишком большой мощности может повлиять на стабильность вашего проекта. Но дайте им слишком мало мощности, и им будет трудно решить свои собственные проблемы — в этом случае вы можете просто не использовать плагин.
Что еще мы можем сделать?
Нам еще предстоит много работы по совершенствованию нашей системы.
Мы можем добавить обработку ошибок, чтобы уведомить автора плагина, если автор плагина забудет определить имя или возвращаемое значение. Хорошо думать как разработчик QA и представлять, как наши системы могут сломаться, чтобы мы могли заранее справляться с такими ситуациями.
Мы можем расширить функционал плагина. В настоящее время плагин BetaCalc может добавить кнопку. Но что, если бы он также мог регистрировать обратные вызовы для некоторых событий жизненного цикла (например, когда калькулятор собирается отобразить значение)? Или что, если бы для него было специальное место для хранения части состояния при множественных взаимодействиях? Откроет ли это новые варианты использования?
Мы также можем расширить функциональность регистрации плагина. Что, если бы плагин можно было зарегистрировать с некоторой начальной настройкой? Делает ли это плагин более гибким? Что, если бы автор плагина захотел зарегистрировать целый набор кнопок вместо одной кнопки — например, «Пакет статистики BetaCalc»? Какие изменения необходимы для поддержки этого?
ваша система плагинов
И BetaCalc, и его система плагинов очень просты. Если ваш проект больше, вам нужно будет изучить некоторые другие архитектуры плагинов.
Хорошей отправной точкой является просмотр существующих проектов в поисках примеров успешных систем плагинов. Для JavaScript это может означать jQuery, Gatsby, D3, CKEditor или другие. Вы также можете ознакомиться с различными шаблонами проектирования JavaScript, каждый из которых предоставляет свой интерфейс и степень связанности, что дает вам множество хороших вариантов архитектуры плагинов. Знание этих параметров поможет вам лучше сбалансировать потребности всех, кто использует ваш проект.
Помимо самих шаблонов, для принятия таких решений можно использовать множество хороших принципов разработки программного обеспечения. Я упомянул несколько подходов (таких как принцип открытого-закрытого и слабая связь), но некоторые другие связанные подходы включают закон Деметры и внедрение зависимостей.
Я знаю, что это звучит как много, но вы должны провести исследование. Нет ничего более болезненного, чем когда каждый переписывает свой плагин, потому что вам нужно изменить архитектуру плагина. Это быстрый способ потерять доверие и заставить людей потерять уверенность в своих будущих вкладах.
Суммировать
Написать хорошую архитектуру плагина с нуля сложно! Вы должны сбалансировать множество соображений, чтобы построить систему, которая удовлетворит все потребности. Это достаточно просто? Может ли функция быть мощной? Будет ли это работать в долгосрочной перспективе?
Но это того стоит, наличие хорошей системы плагинов помогает всем, а разработчики вольны решать свои проблемы. Конечные пользователи могут выбирать из большого набора функций. Вы можете создать экосистему и сообщество вокруг своего проекта. Это ситуация с тремя выигрышами.
Рекомендуемое чтение
- Основные навыки разработки полного стека: 13 лучших практик для создания RESTful API
- Обмен идеями: как попробовать создать собственный CSS-фреймворк?
- Создание программы прогноза погоды из командной строки с помощью Deno
- 10 красивых светлых тем VSCode
- Недооцененный фильтр CSS: тень
- Я слышал, что вы умеете пользоваться Vue. Вы освоили эти 9 технологий Vue?
оригинал:CSS-tricks.com/designing - ах...
Автор: Брайан Браун