3 мая 2019 в 19:21 (МСК)
| сохранено
9 мая 2019 в 19:22 (МСК)
H Змейка на С# и Onion aka Clean Architecture
в черновиках
Tutorial
В прошлой своей статье я вскользь упомянул Onion архитектуру. Там было в основном про то что не надо лишние библиотеки и папки создавать, что надо делить код на модули и что можно писать код прямо в контроллер и использовать Entity Framework там же напрямую
НО Домен все равно должен быть отдельно и все вычисления должны быть в нем. Теперь хочу поговорить о луковой архитектуре. Больше всего подходящей для сложного приложения с большим количеством логики. В этой статье в качестве примера я буду использовать игру "
Змейка " потому что в ней достаточно логики для «богатого» домена
Легенда
Красным цветом указана зависимости.
Зеленым цветом указаны важные группы. Под — слои
Синим цветом разделены основные слоим которые желательно держать отдельно
Терминология
Анемичная модель : Модель данных без логики.
ValueObject : Неизменяемое хранилище данных без уникального идентификатор
Entity : Объект c уникальным идентификатором
Aggregate : Объект содержащий в себе Entity. Обладает уникальным идентификатором.
Data Layer — Repository : Изолирует нас от того что мы используем . Хранилище наших Aggregate
UseCase/Interactor : Изолирует нас от того что использует нас . Например от ASP.NET, gRPC, WCF, WPF, WinForms. Может вызывать Repository когда это нужно. Сам почти ничего не делает и не хранит. Тут должна быть минимальная логика. Только использует Entity, Aggregate, ValueObject и Repository. В Анемичной модели наоборот делает все, тут вся логика.
DomainEvent : Событие которое случилось в Домене и на которое внешний мир должен как-то среагировать. Можно сделать просто булево свойство или коллекцию с объектами у вашего домена в которую добавлять события. Обрабатывать их можно в ApplicationService/UseCase/Interactor.
Суть
Union aka Clean это про то что у вас должен быть отдельно:
Класс, который делает вычисления или является объектным представление какой-то сущности в приложении. Calculator и ResultValueObject
Класс, который пишет данные в хранилище данных или читает их оттуда. CalculatorRepository
Класс, который реагируют на действия пользователя. CalculatorService
Calculator и ResultValueObject должны быть независимы от CalculatorRepository и CalculatorService
Пример: Игра змейка
github.com/VictoremWinbringer/SnakeGameWithOnionAkaCleanArchitecture
Литература
Domain Driven Design – simplifying the complicated
Заблуждения Clean Architecture
UPD
В комментариях пожаловались что картинка у меня кривая поэтому добавил еще одну.
Тут замечание: Gateway == Repository
комментарии (6)