Подтвердить что ты не робот

Где реализовать Automapper в DDD + многоуровневой архитектуре

Фон: Для моей собственной ясности/самообразования я пытаюсь реализовать простое приложение для ввода заявок с использованием TDD + DDD. Моя основная цель - сохранить архитектуру чистой, разделив проблемы.

У меня есть четыре слоя (на данный момент)...

  • Стойкость/DAL с классом CustomerRepository, который может выполнять GetById, Save, операции над "агрегированным корнем", Клиентом и связанными с ним ордерами и OrderItems. Чтобы обеспечить "инъекцию зависимости бедных людей"

  • Уровень домена /BLL, содержащий классы бизнес-объектов, которые выполняют мелкомасштабные операции, чтобы помочь создавать новые заказы, применяя налоговые, скидки, логику доставки на основе размера заказа и местоположения клиента.

  • Прикладной фасад (службы приложений/оркестровка), содержащий короткие, более грубые классы для организации "бизнес-сущностей" и уменьшения болтовни с презентацией (и, возможно, уровня WebServices).

  • Уровень представления

Кроме того, я хочу передать POCO DTO между ключевыми слоями... в частности между уровнями Persistence = > Domain и ApplicationFacade = > Presentation. Итак, у меня есть CustomerDto, OrderDto, OrderItemDto с соответствующими отношениями, определенными в общем пакете.

Я хочу внедрить реализацию ICustomerRepository в класс "бизнес-объект" Customer с использованием Constructor Injection, а затем вызвать Customer.Save() в "бизнес-сущности", чтобы запустить процесс создания/обновления, в конечном итоге вызвать Сохранить метод в CustomerRepository. В конце концов, Клиент является "совокупным корнем" и имеет всю необходимую информацию для сохранения... он также является "хранителем" введенного CustomerRepository.

Проблема: Здесь я попал в ловушку. Я хочу, чтобы уровень Domain/BLL был как можно более чистым и не связывал его с сторонними фреймворками и API-интерфейсами, , но метод Customer.Save() должен переводить "совокупный корень" клиента, и все его Заказы и OrderItems в их версии DTO для транспорта на вложенный слой Persistence CustomerRepository... и это работа для Automapper.

Проблема в том, что... Если я не стану Automapper в слое Domain/BLL, я не уверен, что , где он должен идти.

Неплохо, если вы поместите его в ApplicationFacade, даже если это задание - оркестровка.

Он определенно не хочет помещать его в слой Domain/BLL, потому что я хочу сохранить его в чистом виде.

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

4b9b3361

Ответ 1

Чтобы ответить на ваш конкретный вопрос, я буду говорить более подробно о вашей архитектуре. Архитектура, которую вы разработали для своего проекта, тонко отличается от типичной архитектуры, используемой с DDD. Хотя способ разделения обязанностей типичен, в DDD классы домена не несут ответственности за их собственную постоянство. На самом деле мантра DDD невосприимчивость к сохранению. Это в основном означает, что классы домена являются персистентностью невежественными - они не имеют метода Save. Вместо этого службы приложений (уровень фасада приложений в вашей архитектуре) координируют с репозиториями для восстановления и сохранения объектов домена.

Далее, при реализации репозиториев обычно нет необходимости в явном DTO между базовой технологией сохранения и классами домена. С ORM, такими как NHibernate и EF, сопоставление между классами домена и реляционными таблицами выражается либо с помощью классов сопоставления, либо с использованием XML-конфигураций. В результате ваши классы домена отображаются неявно - нет необходимости в DTO. Некоторые случаи требуют DTO, и в этом случае сопоставление между DTO и классом домена должно быть инкапсулировано реализацией репозитория. Это одно место, где вы могли бы вызывать AutoMapper.

Наконец, распространенной практикой является общение между уровнем представления и уровнем приложения/домена с DTO. Чтобы точно определить, где должно происходить сопоставление, вам нужно углубиться в архитектуру, которая наилучшим образом соответствует вашему проекту. Большинство современных DDD-архитектур основаны на гексагональной архитектуре . В гексагональной архитектуре ваш домен находится в центре, а все остальные "слои" адаптируют домен к конкретным технологиям. Например, репозиторий можно рассматривать как adapter между доменом и конкретной технологией базы данных. ASP.NET WebAPI можно рассматривать как адаптер между доменом и HTTP/REST. Аналогично, уровень представления можно рассматривать как адаптер между доменом и конкретным. DTO могут проявляться в каждом из этих адаптеров, и ответственность адаптера заключается в том, чтобы сопоставлять их с этими DTO.

Типичным примером может служить использование служб приложений для создания фасада над вашим доменом. Никаких DTO в игре еще нет. Затем вы создаете сервисный уровень (открыть службу хоста в DDD) с помощью ASP.NET WebAPI - адаптера. Вы создаете специфические DTO для ASP.NET WebAPI, и именно этот адаптер должен сопоставляться с этими DTO и обратно. Поэтому, если вы используете AutoMapper, его следует вызвать в этом слое. Это можно сделать либо явно, либо в aspect-oriented с помощью фильтров действий. То же самое относится к слою представления. Уровень презентации можно связать непосредственно с сервисами приложений или с открытым хостингом ASP.NET WebAPI. В любом случае, слой представления должен отображать между классами домена (из службы приложения или DTO из WebAPI) и его собственных примитивов, таких как ViewModel.