Как создать гибкую архитектуру плагина?


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

  • база данных не является отличным местом для хранения информации о конфигурации, особенно в сочетании с данными
  • попытка этого с иерархией наследования требует знание о плагинах, которые нужно закодировать, означает, что архитектура плагина не такая уж динамичная
  • файлы конфигурации хорошо работают для предоставления простой информации, но не могут обрабатывать более сложные поведения
  • библиотеки, кажется, работают хорошо, но односторонние зависимости должны быть тщательно созданы.

поскольку я стремлюсь учиться у различных архитектур, с которыми я работал, я также обращаюсь к сообществу за предложениями. Как вы реализовали Твердая архитектура плагина? Какой был ваш худший провал (или худший провал, который вы видели)? Что бы вы сделали, если бы собирались реализовать новую архитектуру плагинов? Какой SDK или проект с открытым исходным кодом, с которым вы работали, имеет лучший пример хорошей архитектуры?

несколько примеров, которые я нашел сам:

эти примеры, похоже, играют на различные сильные стороны языка. Это хорошая архитектура плагина обязательно привязан к языку? Лучше всего использовать инструменты для создания архитектуры плагина, или сделать это на своих собственных следующих моделях?

8 130

8 ответов:

Это не ответ аж куча потенциально полезных замечаний / примеров.

  • один эффективный способ сделать ваше приложение расширяемым-это представить его внутренние компоненты в качестве языка сценариев и написать все материалы верхнего уровня на этом языке. Это делает его вполне модифицируемым и практически будущим доказательством (если ваши примитивы хорошо выбраны и реализованы). История успеха такого рода вещей-Emacs. Я предпочитаю этот стиль затмение система плагинов, потому что если я хочу расширить функциональность, мне не нужно изучать API и писать/компилировать отдельный плагин. Я могу написать 3-строчный фрагмент в самом текущем буфере, оценить его и использовать. Очень плавная кривая обучения и очень приятные результаты.

  • одно приложение, которое я немного расширил, это Trac. Он имеет компонентную архитектуру, которая в этой ситуации означает, что задачи делегируются модулям, которые объявляют точки расширения. Затем вы можете реализовать другие компоненты, которые будут вписываться в эти точки и изменять поток. Это немного похоже на предложение Калки выше.

  • еще один хороший-это py.тест. Это следует из философии "лучший API-это не API" и полагается исключительно на крючки, вызываемые на каждом уровне. Вы можете переопределить эти крючки в файлах / функциях, названных в соответствии с соглашением, и изменить поведение. Вы можете посмотреть список плагинов на сайте, чтобы увидеть, как быстро/легко они могут быть реализованы.

несколько общих замечаний.

  • старайтесь, чтобы ваше нерасширяемое / не изменяемое пользователем ядро было как можно меньше. Делегируйте все, что вы можете, на более высокий уровень, чтобы увеличить расширяемость. Меньше вещей, чтобы исправить в ядре, то в случае плохого выбора.
  • связанный с вышеизложенным пункт заключается в том, что вы не должны принимать слишком много решений о направлении вашего проекта в самом начале. Реализуйте наименьшее необходимое подмножество, а затем начните писать плагины.
  • если вы внедряете язык сценариев, убедитесь, что это полный, в котором вы можете писать общие программы, а не игрушечный язык просто для вашего приложения.
  • уменьшить шаблон столько, сколько вы можете. Не беспокойтесь о подклассах, сложных API, регистрации плагинов и тому подобных вещах. Постарайтесь, чтобы это было просто, так что это легко и не только возможно продлевать. Это позволит использовать ваш плагин API больше и будет стимулировать конечных пользователей писать плагины. Не только разработчики плагинов. Пи.тест это хорошо. Затмение, насколько я знаю, не.

по моему опыту я обнаружил, что есть действительно два типа плагинов архитектуры.

  1. следуя Eclipse model который предназначен для обеспечения свободы и является открытым.
  2. другой обычно требует плагинов, чтобы следовать narrow API потому что плагин будет заполнять определенную функцию.

чтобы выразить это по-другому, один позволяет плагинам получить доступ к вашему приложению в то время как другой приложения доступ к плагинам.

различие является тонким, а иногда нет уникален... вы хотите для вашего приложения.

у меня нет тонны опыта работы с Eclipse/открытием вашего приложения для модели плагинов (статья в сообщении Kalkie отличная). Я немного читал о том, как затмение делает вещи, но не более того.

Yegge это блог свойства немного рассказывает о том, как Использование шаблона свойств позволяет использовать плагины и расширяемость.

большая часть работы, которую я сделал, использовала архитектуру плагинов, чтобы позволить моему приложению получать доступ к плагинам, таким как данные времени/отображения/карты и т. д.

лет назад я бы создал фабрики, менеджеры плагинов и конфигурационные файлы для управления всем этим и позволил мне определить, какой плагин использовать во время выполнения.

  • теперь у меня обычно просто есть DI framework сделайте большую часть этой работы.

мне все еще нужно написать адаптеры для использования третьей стороной библиотеки, но они обычно не так уж и плохи.

одна из лучших архитектур плагинов, которые я видел, реализована в Eclipse. Вместо того, чтобы иметь приложение с моделью плагина, все это плагин. Базовое приложение само по себе является подключаемым модулем.

http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html

однажды я работал над проектом, который должен был быть настолько гибким, чтобы каждый клиент мог настроить систему, и единственным хорошим дизайном, который мы нашли, было отправить клиенту компилятор C#!

Если спецификация заполнена такими словами, как:

  • гибкий
  • Плагин
  • настраиваемые

задать множество вопросов о том, как вы будете поддерживать систему (и как она оплачивается, так как каждый клиент будет думать, что их дело нормальный случай и не должен нуждаться в каких-либо плагинах.), как по моему опыту

поддержка клиентов (или fount-line поддержка людей) написание Плагины намного сложнее, чем Архитектура

обычно я использую MEF. Управляемая платформа расширяемости (или MEF для краткости) упрощает создание расширяемых приложений. MEF предлагает возможности обнаружения и компоновки, которые можно использовать для загрузки расширений приложений.

Если вам интересно прочитать больше...

я опишу довольно простую технику, которую я использовал в прошлом. Этот подход использует отражение C#, чтобы помочь в процессе загрузки плагина. Этот метод может быть изменен, поэтому он применим к C++, но вы теряете удобство использования отражения.

An IPlugin интерфейс используется для идентификации классов, реализующих Плагины. Методы добавляются в интерфейс, чтобы позволить приложению взаимодействовать с плагином. Например,Init метод, который приложение будет использовать, чтобы проинструктировать плагин для инициализации.

для поиска плагинов приложение сканирует папку плагинов для сборок .Net. Каждая сборка загружается. Отражение используется для поиска классов, реализующих IPlugin. Создается экземпляр каждого класса плагина.

(кроме того, Xml-файл может содержать список сборок и классов для загрузки. Это может помочь производительности, но я никогда не находил проблемы с производительностью).

The Init метод вызывается для каждого объекта. Передается ссылка на объект, реализующий интерфейс приложения:IApplication (или что-то еще с именем, характерным для вашего приложения, например ITextEditorApplication).

IApplication содержит методы, которые позволяют плагину взаимодействовать с приложением. Например, если вы пишете текстовый редактор, этот интерфейс будет OpenDocuments свойство, которое позволяет плагинам перечислять коллекцию открытых в данный момент документы.

эта система плагинов может быть расширена до языков сценариев, например Lua, путем создания производного класса плагинов, например LuaPlugin что нападающие IPlugin функции и интерфейс приложения к сценарию Lua.

этот метод позволяет итеративно реализовать ваш IPlugin,IApplication и другие прикладные интерфейсы во время разработки. Когда приложение завершено и красиво рефакторингу вы сможете оформить интерфейсов, и вы должны иметь хорошая система, для которой пользователи могут писать свои собственные плагины.

Я думаю, вам нужно сначала ответить на вопрос: "Какие компоненты должны быть Плагины?" Вы хотите сохранить это число до абсолютного минимума или количество комбинаций, которые вы должны проверить взрывается. Попробуйте отделить ваш основной продукт (который не должен иметь слишком много гибкости) от функциональности плагина.

Я обнаружил, что принцип IOC (инверсия управления) (read springframework) хорошо работает для обеспечения гибкой базы, к которой вы можете добавить специализацию чтобы упростить разработку плагинов.

  • вы можете сканировать контейнер для механизма "интерфейс как реклама типа плагина".
  • вы можете использовать контейнер для введения общих зависимостей, которые могут потребоваться плагинам (например, ResourceLoaderAware или MessageSourceAware).

интерфейс с динамической функциональностью, в то время как Скрипты, как правило, подчеркивают функциональность с динамическим интерфейсом.

Я обнаружил, что архитектура, основанная на скрипты управление библиотеки кажется, работает лучше всего. Язык сценариев позволяет высокоуровневым манипуляциям с библиотеками более низкого уровня, и библиотеки, таким образом, освобождаются от любого конкретного интерфейса, оставляя все взаимодействие на уровне приложения в более гибких руках системы сценариев.

чтобы это работало, система сценариев должна иметь довольно надежный API, с крючками для данные приложения, логика и графический интерфейс, а также базовая функциональность импорта и выполнения кода из библиотек. Кроме того, скрипты обычно должны быть безопасное в том смысле, что приложение может корректно восстановить от плохо написанного сценария. Использование системы сценариев в качестве уровня косвенности означает, что приложение может более легко отделить себя в случае чего-то плохого™.

средства упаковки плагинов во многом зависят от личных предпочтений, но вы никогда не ошибетесь со сжатым архивом с простым интерфейсом, скажем PluginName.ext в корневом каталоге.