Я смотрю на разработку нового решения, которое по своей природе является очень модульным, и мне хотелось бы создать структуру, поддерживающую этот дизайн, чтобы облегчить расширение в будущем, четкое разделение проблем, лицензирование по модулям и т. Д. В Интернете я обнаружил, что модульные или составные приложения ориентированы на пользовательский интерфейс, ориентированы на Silverlight, WPF и т. д. В моем случае я разрабатываю приложение службы WCF, которое будет использоваться другими разработчиками, работающими над различными проектами пользовательского интерфейса.
Фон
Цель моего проекта - создать централизованный источник бизнес-логики / предметной логики для поддержки нескольких наших бизнес-приложений, которые в настоящее время дублируют процессы, правила и т. Д. И хотя не все преимущества модульности будут достигнуты, я хотел бы воспользоваться возможность создать структуру, которая будет использовать те части, которые мы можем использовать в своих интересах.
Я начал разработку с рассмотрения API, предоставляемого сервисным приложением. Понятно, что сервисы можно разделить по модульным линиям, которые я рассматривал. Например, у меня будут сервисы FinanceService, InventoryService, PersonnelService и т. Д., Которые группируют мои сервисные операции для обеспечения высокой согласованности в API, сохраняя низкую связь, поэтому клиенты должны использовать только те услуги, которые имеют отношение к их приложению.
Для меня имеет смысл иметь отдельные модули для каждой из этих служб, такие как MyApp.Finance, MyApp.Inventory, My.Personnel и так далее. Сквозные проблемы и общие типы будут в общей сборке MyApp. Отсюда я немного связан.
(О, я должен упомянуть, что я буду использовать IoC-контейнер для Dependency Injection, чтобы оставить приложение свободно связанным. Я не буду упоминать какой, потому что я не хочу открывать ящик Пандоры!)
В MyApp.ServiceHost я создам файл хоста службы (.svc), соответствующий каждому модулю, например FinanceService.svc. Хосту службы необходимо имя службы, которое соответствует информации в файле конфигурации, который содержит интерфейс, определяющий контракт на обслуживание. Затем конфигурация IoC используется для сопоставления конкретной реализации используемого интерфейса.
1. Должен ли сервисный уровень реализовывать API и делегировать модулям, или модули должны быть автономными (в том смысле, что они содержат все, что связано с этим модулем, включая реализацию сервиса)?
Одним из способов решения этой проблемы является наличие «модуля» MyApp.Services, который содержит реализацию контрактов на обслуживание. Каждый класс обслуживания просто делегирует другому классу соответствующий модуль, который содержит логику домена для операции. Например, WCF-класс FinanceService в MyApp.Services делегирует другой интерфейс, который реализован в модуле Finance для выполнения операции. Это позволило бы мне поддерживать тонкий фасад службы и «подключать» реализацию к реализации службы, а также избавить модули от необходимости беспокоиться о WCF, например.
С другой стороны, может быть, предпочтительнее иметь каждый модуль в отдельности, так как он имеет интерфейс и реализацию. Хост обслуживания относится к интерфейсу контракта на обслуживание, найденному в модуле, и IoC также настроен на использование соответствующей реализации из модуля. Это означает, что добавление нового модуля может быть выполнено без каких-либо изменений на уровне службы, кроме добавления нового файла .svc и информации о конфигурации IoC.
Я думаю о влиянии, если я переключусь со стандартного WCF на интерфейс службы RESTful или, возможно, перейду к службам RIA или что-то в этом роде. Если каждый модуль содержит реализацию контракта на обслуживание, тогда мне придется вносить изменения в каждый модуль, если я меняю технологию или подход к обслуживанию. Но если фасад является собственным модулем, мне нужно только поменять эту часть, чтобы внести изменения. Модули должны были бы реализовать другой набор контрактов (интерфейсов), возможно, определенных в общей сборке ???
2. Каков наилучший способ управления совместным использованием ресурсов между модулями и / или зависимостями между модулями?
Взять, к примеру, операцию получения. На первый взгляд имеет смысл, что это входит в модуль инвентаризации, поскольку получение товара является функцией инвентаризации. Однако есть и финансовый аспект, который заключается в том, что нам необходимо создать квитанцию и авторизовать платеж.
С одной стороны, я ожидал бы использовать некоторый тип доменных событий / сообщений для сообщения об операции. Модуль Inventory вызывает GoodsReceivedEvent, который обрабатывается финансовым модулем, чтобы сгенерировать квитанцию и инициировать процесс оплаты. Однако это означает, что Финансовому модулю необходимо знать об элементах инвентаря, которые были получены. Я могу просто ссылаться на них по идентификатору, но что, если мне потребуется дополнительная информация для квитанции, такая как имя и / или описание, стоимость единицы и т. Д.? Имеет ли смысл для каждого модуля иметь собственную версию предмета инвентаря, разработанную для удовлетворения потребностей этого модуля? В этом случае Финансовый модуль должен будет выполнить собственный поиск элементов инвентаря при обработке GoodsReceivedEvent.
...
Я использовал этот пример специально, потому что много работал с различными ERP-системами и знаю, что они разработаны с таким модульным типом - я просто не знаю как. Я также не упоминаю об этом выше, но я предпочитаю следовать принципам Domain Driven Design при разработке решения и считаю, что этот тип модульности вписывается в эту область.
Любая помощь, чтобы моя голова обернулась вокруг этого очень ценится.