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

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

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

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

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

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

8 ответов


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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. Создается экземпляр каждого класса plugin.

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

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

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

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

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


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

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

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

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

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

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

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