Я дивлюсь на створення нового рішення, яке є дуже модульним за своєю суттю і хотів би створити структуру, яка підтримує цей дизайн, щоб забезпечити легке розширення в майбутньому, чітке розділення проблем, ліцензування за модулем тощо. Більшість того, що я маю В Інтернеті про модульні або складені програми є орієнтовані на інтерфейс користувача, орієнтовані на Silverlight, WPF тощо. У моєму випадку я розробляю службовий додаток WCF, яке споживають інші розробники, що працюють над різними проектами інтерфейсу.
Фон
Мета мого проекту - створити централізоване джерело логіки бізнесу / домену для підтримки декількох наших бізнес-додатків, які наразі дублюють процес, правила і т. Д. І хоча не всі переваги модульності будуть досягнуті, я хотів би скористатися можливість створити рамку, яка буде використовувати ті частини, якими ми можемо скористатися.
Я розпочав розробку, переглянувши API, виставлений службовою програмою. Зрозуміло, що послуги можна розділити за модульними лініями, які я розглядав. Наприклад, у мене будуть служби FinanceService, InventoryService, PersonnelService тощо., Які групують мої сервісні операції для забезпечення високої згуртованості в API, зберігаючи при цьому зв'язок низьким, щоб клієнти повинні споживати лише ті послуги, які стосуються їх застосування.
Для мене є сенс, що я можу мати окремі модулі для кожної з цих служб, такі як MyApp.Finance, MyApp.Inventory, My.Personnel тощо. Наскрізні проблеми та спільні типи були б у спільній збірці MyApp. Звідси я трохи прив’язуюсь.
(О, я повинен зазначити, що я буду використовувати контейнер IoC для ін'єкцій залежностей, щоб додаток було вільно пов'язане. Я не згадаю, який з них не хочу відкривати вікно Пандори!)
У MyApp.ServiceHost я створю файл хосту служби (.svc), відповідний кожному модулю, наприклад FinanceService.svc. Хост сервісу потребує ім'я послуги, яке відповідає інформації у файлі конфігурації, що містить інтерфейс, що визначає договір на обслуговування. Потім конфігурація IoC використовується для відображення конкретної реалізації інтерфейсу, який слід використовувати.
1. Чи повинен сервісний рівень реалізовувати API та делегувати модулі, або вони повинні бути самостійними (якщо вони містять все, що стосується цього модуля, включаючи реалізацію послуги)?
Один із способів підходу до проблеми - мати "модуль" MyApp.Services, який містить реалізацію договорів на обслуговування. Кожен клас сервісу просто делегує інший клас у відповідний модуль, який містить логіку домену для операції. Наприклад, клас WCF FinanceService в MyApp.Services делегує інший інтерфейс, який реалізується в модулі Фінанси для здійснення операції. Це дозволило б мені підтримувати тонкий фасад сервісу і «підключати» до виконання службу, а також усунути необхідність, щоб, наприклад, модулі турбувалися про WCF.
З іншого боку, можливо, бажано мати кожен модуль самостійним, оскільки він має інтерфейс та реалізацію. Хост сервісу посилається на інтерфейс контракту на послугу, знайдений в модулі, і IoC налаштований для використання відповідної реалізації також від модуля. Це означає, що додавання нового модуля можна проводити без будь-яких змін сервісного рівня, окрім додавання нового файлу .svc та інформації конфігурації IoC.
Я думаю про вплив, якщо я перейду зі стандартного WCF на інтерфейс RESTful сервісу або, можливо, перейду на послуги RIA чи щось таке. Якщо кожен модуль містить реалізацію договору на обслуговування, тоді я повинен внести зміни в кожен модуль, якщо я зміню технологію обслуговування або підхід. Але, якщо фасад - це власний модуль, то мені залишається лише поміняти цю частину, щоб внести зміни. Потім модулі повинні були б реалізувати інший набір контрактів (інтерфейсів), можливо визначених у спільній збірці ???
2. Який найкращий спосіб обробляти ресурси між модулями та / або залежностями між модулями?
Візьмемо, наприклад, операцію отримання. Спочатку рум'яна має сенс, що це переходить в модуль інвентаризації, оскільки отримання товарів є функцією інвентаризації. Однак є й фінансовий аспект у тому, що нам потрібно створити квитанцію та дозволити платіж.
З одного боку, я б очікував використовувати деякий тип подій / повідомлень домену для передачі операції. Модуль «Інвентаризація» піднімає CommReceivedEvent, який обробляється Фінансовим модулем, щоб генерувати квитанцію та ініціювати процес оплати. Однак це означає, що Фінансовий модуль повинен знати про товари, що надійшли. Я можу просто посилатися на них за ідентифікатором, але що робити, якщо мені потрібна додаткова інформація для квитанції, наприклад, ім'я та / або опис, вартість одиниці тощо? Чи має сенс для кожного модуля мати свою власну версію товарно-матеріальних цінностей, розроблену відповідно до потреб цього модуля? У цьому випадку Фінансовий модуль повинен був би здійснити власний пошук товарно-матеріальних цінностей під час обробки CommReceivedEvent.
...
Я використовував цей приклад навмисно, тому що я багато працював з різними ERP-системами і знаю, що вони розроблені з таким типом модульності - я просто не знаю як. Я також прямо не згадую це вище, але я вважаю за краще керуватися принципами дизайну, керованим доменом при архітектурі рішення, і вважаю, що цей тип модульності вписується прямо в цю область.
Будемо дуже вдячні за будь-яку допомогу в закручуванні голови.