Архитектура для расширения / связи плагинов - PullRequest
5 голосов
/ 18 ноября 2009

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

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

  • События: добавление статических событий ко всем вещам, которые мы хотим сделать «расширяемыми». Например, если я хочу добавить пользовательскую проверку для класса User, я могу добавить обработчик статических событий OnValidation и добавить к нему события из плагина при его создании.
  • Обмен сообщениями: наличие шины и сообщений. Плагин может подписаться на определенное сообщение и делать что-то, когда другой класс публикует это сообщение. Сообщение должно содержать контекст, в котором может работать плагин. В случае проверки логический уровень опубликует сообщение UserValidation, а плагин будет действовать при получении сообщения.
  • Интерфейсы. Хост-приложение отвечает за вызов всех плагинов, реализующих определенные интерфейсы, и предоставляет им контекст текущей операции. В случае проверки плагин может реализовывать IValidator или IUserValidator с методом Validate (объектный контекст).

Вы когда-нибудь пользовались одним из раскрытых подходов? Какой из них работал лучше для вас?

И прежде чем вы спросите, наше приложение представляет собой расширяемое ядро ​​(управление пользователями, пользователями и контентом), для создания наших клиентских веб-приложений, ориентированных на контент. Все построено на ASP.NET MVC.

Ответы [ 2 ]

2 голосов
/ 18 ноября 2009

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: Ларс сделал важный комментарий в своем комментарии - если ваша платформа поддерживает исключения, вы можете централизовать большую часть обработки ошибок при использовании прямых интерфейсов, освобождая плагины от необходимости обрабатывать ошибки, которые универсальный и, возможно, превосходит их конкретный домен (например, «ошибка загрузки плагина» или «ошибка открытия файла»). Однако такие преимущества могут исчезнуть, если вам придется поддерживать интерфейсы каждый раз, когда вы добавляете плагины. В худшем случае, когда интерфейсы начинают становиться непоследовательными, вы не понимаете, что они должны поддерживать с самого начала. Рефакторинг всего дизайна интерфейса, когда уже разработано значительное количество плагинов, - задача не из легких.

0 голосов
/ 18 ноября 2009

Я бы пошел с шаблоном Наблюдатель . Из GOF:

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

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

...