@Uriel

Есть ли какая-то хорошая практика по интеграции функциональности из независимых библиотек для последующего использования?

Добрый день!

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

Есть условный "внутренний корпоративный фреймворк" для разработки приложений на нём. И есть в нём две совершенно отдельных сущности: лицензирование (DRM, защита от копирования, вот это вот всё) и сервисы Windows. Ни одна из библиотек не знает друг о друге, но обе ссылаются на какие-то общие более низкоуровневые библиотеки. Конечное приложение может добавить любую из них, либо обе. Получается что-то вроде плагинов.

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

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

Мне видятся следующие способы решения данной проблемы:

1. Вся функциональность живёт в одной толстой библиотеке, и всё знает обо всём. По сути сейчас такой подход и используется, но очень уж хочется отделить всё это друг от друга.

2. Заводится три библиотеки: Licensing, Service и Licensing.Service. Но это путь к безумию, так как по сути подобную библиотеку придётся заводить на каждую возможную комбинацию используемой функциональности.

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

4. Наоборот заводится библиотека, которая ссылается на все-все-все модули и в ней идёт оркестровка взаимных зависимостей между ними.

5. Использовать что-то вроде общей шины данных, по которой будут бегать команды вроде "LicenseChanged", а модуль сервиса может на них среагировать. По сути все снова знают обо всех, но типизация становится строковой.

Читаю Хабр довольно давно, но не припомню, чтобы встречал какие-то размышления именно на этот счёт. Буду благодарен, если кто-то сможет ткнуть носом в статью/книгу. Либо я упускаю что-то очевидное, либо в общем виде оно не решается. :) Вообще язык C#, но думаю, что это не принципиально.
  • Вопрос задан
  • 44 просмотра
Пригласить эксперта
Ответы на вопрос 2
@0nkery
Вы можете использовать общую шину, подключить туда две сущности: Licensing и Service, а между ними поставить сущность, которая знает о событии LicenceChanged и знает, что при этом событии нужно перезапустить сервисы, а так же, как именно это можно сделать (обращается к Service). Если обращаться к Service по той же шине, то в ситуации, когда Service недоступен (не подключен например), ничего происходить и не будет -- то есть, не надо будет явно обрабатывать кейс с отсутствием Service внутри сущности-обвязки.

Плюс такого решения -- обвязка не зависит от кода конкретных реализаций License и Service. Строковую типизацию вы можете и не делать, если шина умеет в разные типы сообщений так или иначе -- в крайнем случае, хотя бы сериализацию для событий какую-то можно придумать. К тому же события все равно несут какую-то информацию помимо названия, так что какая-то структура этих событий не помешает. Но здесь я уже увлекся, ибо никаких таких вводных не было. :)

Я рассуждаю в рамках акторной системы, где такие сценарии мне обдумывать проще, но кажется, что и в C# внутри какого-то другого подхода это реализуемо. :)
Ответ написан
Комментировать
@Uriel Автор вопроса
Благодарю за ответ! Я уж и не думал, что кто-то его увидит. :)

Честно говоря, с шинами пока явно не сталкивался в проектах, поэтому могу чего-то не понимать. Фраза "между ними поставить сущность, которая знает о событии LicenceChanged" меня смутила. А куда эту сущность добавлять? Где она будет жить? В конечном проекте, который будет использовать эти библиотеки? Так это дублировать в каждом таком проекте придётся. Собственно у меня основной вопрос и заключается в терзаниях на этот счёт.

С типизацией мне тоже этот момент неясен. Чтобы типизация была не строковой, то нужно где-то описать тип этого события. Логично поселить его в библиотеку Licensing, так как это её событие. Но чтобы сущность, знающая о нём и перезапускающая сервис понимала этот тип, нужно добавить ссылку на эту самую библиотеку Licensing к ней. Собственно опять же вопрос: куда, где будет жить эта обвязка?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы