Blazor asp.net структура решения при луковичной архитектуре
Разрабатываю Blazor WASM приложение + ASP.NET и решил переписать его с использованием луковичной архитектуры, т.к с учетом даже моего опыта вижу огрехи и некоторые неудобства при текущей архитектуре(Client+Server+Shared). Проект делаю с использованием CQRS.
Есть несколько больших примеров на blazor и один из них этот.
Уровни в данном решении:
Core
- Domain - основные сущности в бд
- Application - базовый уровень всего приложения.
Infrastructure
- Infrastructure - серверная логика
WEB
- Server
- Client
- Client.Infrastructure - логика для клиента
Что я не могу понять?
Как я понимаю сейчас:
Application уровень - базовый уровень, без которого невозможна работа ни клиента, ни сервера. На данном уровне нужно объявлять самый минимум, который уже на 90% будет раскрывать сервер и в работе использовать клиент.
Что я вижу
Да, в этом уровне создают Exceptions, Responses, Enums и прочие базовые вещи для всего приложения. Но меня конкретно интересует cqrs и сервисы для его работы. Чтобы клиентское приложение или его библиотека(Client.Infrastructure) смогла обращаться к api она должна где-то взять эти commands/queries и их логично хранить в уровне приложения, но зачем в этом уровень везде объявляют и логику(nahdlers, validators)?
Не логичнее ли в этом уровне оставить ТОЛЬКО commands/queries без бизнес-логики, а ее перенести в Server.Infrastructure(ну или просто Infrastructure). Зачем каждый раз клиенту отсылать Application.dll, в котором часть кода ему не нужна? Да, насколько я знаю, VS при публикации умеет ужимать .dll и (вроде бы) даже убирать неиспользуемый код для экономии места, но все же.
P.S
Конкретно в проекте из примера Application уровень весит 173кб. Какая из этого часть ненужная(по моему мнению), я не знаю, но думаю внушительная.
UPD:
Копнул чуть глубже и заметил, что для команд и запросов нужна одна и та же валидация как на клиенте, так и на сервере. Два раза копировать ее не хочется, поэтому буду придерживаться такой же логики размещения кода, как и в примере по ссылке.
Ответы (1 шт):
Бизнес-логика должна быть на сервере, но вы не должны класть её в слой инфраструктуры. Валидация, работа с зависимостями, подготовительные приседания перед вызовом команды - это всё логика именно уровня Приложения. В идеале, этот уровень отвечает за склейку всех кубиков, которые у вас в ядре и инфраструктуре, во что-то похожее на приложение.
Приведённый вами пример неплох, но я могу дать вам свежий пример (правда, WASM-вариант), который может получше вам объяснить хорошую структуру клиентского приложения: https://github.com/a-postx/YA.BlazorVkParser
Обратите внимание на то, что находится в слое Приложения: модельки, различный мапинг, кеши форм и так далее т.е. всё то, что формирует приложение как таковое. В инфраструктуре же мы держим только внешние зависимости.
Ключевой момент здесь: слой инфраструктуры зависит от приложения, но никак не наоборот. Если вы обнаруживаете у себя using XXX.Infrastructure в слое приложения, то что-то пошло не так - при подобном просачивании вы уже не сможете легко переехать, скажем, с REST HTTP вызовов на другой транспорт.
К сожалению, серверной части упомянутого приложения нет в открытом доступе, но там работают микросервисы с дизайном, очень похожим на другой открытый пример: https://github.com/a-postx/YA.ServiceTemplate
В клиенте модельки просто скопированы с бекенда, но я не вижу в этом проблемы - ничего не мешает вынести их в общую библиотеку.