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

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

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

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

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

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

Ответ 1

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

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

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

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

Несколько общих пунктов.

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

Ответ 2

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

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

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

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

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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

  • Гибкая
  • Plug-In
  • Настраиваемый

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

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

Ответ 5

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

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

Ответ 6

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

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

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

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

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

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

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

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

Ответ 7

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

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

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

Ответ 8

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

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

Для этого система сценариев должна иметь довольно надежный API, с привязками к данным приложения, логике и графическому интерфейсу, а также базовые функции импорта и выполнения кода из библиотек. Кроме того, скрипты обычно должны быть безопасными в том смысле, что приложение может изящно восстановить из плохо написанного script. Использование системы сценариев в качестве слоя косвенности означает, что приложение может более легко отделить себя в случае Something Bad & trade;.

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