Использование MVVM и DDD в приложении WPF без слишком большого количества классов
У меня есть приложение WPF, где я хочу применить MVVM для уровня представления и DDD для всего приложения. Я очень смущен тем, как я должен применять архитектуру. Можете ли вы дать мне несколько советов, поскольку мне кажется, что я полностью перепутал на данный момент со следующей попыткой дизайна:
У меня есть 4 слоя:
-
Presentation Layer
: здесь находится мое клиентское приложение WPF.
-
Application Layer
. Здесь у меня есть мои службы, которые предполагают связь с услугами домена для бизнес-правил и CRUD. Он работает просто как слой с антикоррупцией между слоями Presentation
и Domain
.
-
Domain Layer
. Здесь у меня есть свои агрегированные объекты, объекты домена и некоторые службы, которые раскрывают бизнес-правила, такие как IsTooOld(Person person)
-
Infrastructure Layer
. Это самый низкий уровень, здесь находится инфраструктура, IRepository
, IEntity
и т.д.
Позвольте создать простой сценарий с этими слоями на основе DDD: иметь объект Person в базе данных, отобразить его, CRUD в базе данных, проверить день рождения людей и показать его пользователю.
Уровень презентации
Я начну с части WPF. Я создаю следующие классы:
-
PersonView
: вид XAML человека
-
PersonViewModel
: ViewModel
, который предоставляет функции для PersonView
. PersonView
связывается с этим, и этот ViewModel
предоставляет значения из PersonModel
-
PersonModel
. Это MVVM-модель, с которой моя PersonViewModel
тесно связана с.
Уровень домена
Это достаточно хорошо для уровня представления. Теперь я хочу подключиться к базе данных, чтобы получить объект person, чтобы представить его.
Я должен создать:
-
PersonEntity
в Domain Layer
: агрегат для объекта базы данных, используемый для сопоставлений с базой данных. Он находится в слое Domain
.
-
Person
в Domain Layer
: Это модель домена DDD. Я приведу здесь немного логики, и я не хочу отправлять объекты объектов, как предлагает DDD.
Уровень приложения
Хорошо, у меня уже есть модели на 3 человека, которые очень похожи друг на друга. Как насчет еще нескольких возможностей для доступа к данным и сервисов?
-
PersonService
в Application Layer
: когда мой уровень представления хочет взаимодействовать с этим слоем, ему необходимо преобразовать его PersonModel
(модель MVVM) в Person
(модель домена). Затем эта служба на прикладном уровне преобразует Person
(модель домена) в PersonEntity
(объект объекта) и выполняет CRUD с базой данных. Эта служба использует еще один PersonService
(см. Ниже) на уровне домена для проверки/применения некоторых бизнес-правил.
-
PersonService
в Domain Layer
: этот уровень работает только с объектом домена Person
. Он имеет правила, связанные с бизнесом, такие как bool IsTooOld(Person person)
.
Подводя итог, я получил 7 классов для простого сценария:
-
Presentation.WpfClient.View.PersonView
-
Presentation.WpfClient.ViewModel.PersonViewModel
-
Presentation.WpfClient.Model.PersonModel
-
Application.ApplicationServices.PersonService
-
Domain.Application.Services.PersonService
-
Domain.Application.Models.Person
-
Domain.Application.DbEntities.PersonEntity
(причина, по которой я создал это, заключается в том, что я не могу использовать сопоставление для сложных объектов домена, поэтому я просто помещаю здесь аннотации данных вместо отображения объектов домена)
Это очень неудобно. Я не уверен, как мне переструктурировать его и принести пользу как дизайну, управляемому доменом, так и шаблонам MVVM. Я действительно застрял, и я действительно с нетерпением жду любых советов или примеров реальной жизни для применения как MVVM, так и проекта, управляемого доменом. Я также открыт для любой обратной связи для соглашений об именах или стратегий для минимизации этой большой работы для простых операций.
У меня все еще есть два конкретных вопроса:
-
Следует ли удалять модели из уровня представления (модели MVVM) и использовать только модели из уровня домена (модели DDD)? Разве это не нарушение MVVM в этот момент?
-
Должен ли я объединять модели сущности (базы данных) с моделями доменов? Разве это не нарушение DDD?
Обновление
Решения, принятые мной:
Наконец, это выглядит так:
-
Presentation.WpfClient.View.PersonView
-
Presentation.WpfClient.ViewModel.PersonViewModel
-
Application.ApplicationServices.PersonService
(crud с некоторой логикой, связанной с приложением) -
Application.ApplicationServices.Mappings
(Здесь есть абстракции и отображения репозитория)
-
Domain.Application.People.Person
(объект объекта в нем ограниченный контекст, объект достаточно умен, чтобы обрабатывать логику домена).
Ответы
Ответ 1
Это слишком много классов для одного понятия.
Должен ли я удалять модели из уровня представления (модели MVVM) и использовать только модели из уровня домена (модели DDD)? Разве это не нарушение MVVM в этот момент?
Да, это предпочтительное решение - это много случаев, особенно если вы не используете механизм связи, такой как WCF. Никакое нарушение здесь, поскольку MVVM не налагает особую реализацию части модели.
Должен ли я объединять модели сущности (базы данных) с моделями доменов? Разве это не нарушение DDD?
Кроме того, да. Разделение объекта на два (объект домена и объект "постоянство" ) обычно приводит к чрезмерной сложности и модели анемичного домена. Здесь более подробно: Наличие модели домена, отделенной от модели сохранения.
В целом, я рекомендую вам посмотреть этот пример. Это похоже на то, что вам нужно: полноценное приложение, написанное в WPF с использованием MVVM и DDD.
Ответ 2
DDD наиболее полезен при решении проблем бизнес-класса. В реальном проекте его следует использовать более гибким способом, чтобы определить, насколько сложным является домен. Я бы хотел использовать подход с несколькими стратегиями для его принятия.
-
В большинстве случаев речь идет о данных CRUD с небольшим изменением структуры данных. Я бы использовал только:
Уровень презентации: ViewModel
Сервисный уровень: ViewModel ↔ Объект Domin
Domain Layer: объект домена, такой же, как Entity
-
Для более сложного Домена, где есть много важной и многоразовой бизнес-логики для объекта Domain, я бы добавил базовый сервис (например, ваш Domain.Application.Services.PersonService).
-
Если для данных процесса существует сложная бизнес-логика для упрощения сопоставления данных между уровнем представления и уровнем Domin Layer. Я бы добавил еще одну модель в Service Layer, аналогичную вашей Presentation.WpfClient.Model.PersonModel.
Итак, в основном архитектура, которую вы сейчас собрали, готова для обработки дела, что ваш домен Person очень сложный в вашем проекте. Но я не вижу его так далеко от вашего описания.
Чтобы ответить на ваши вопросы:
-
Вы можете удалить Presentation.WpfClient.Model.PersonModel в своих моделях MVVM. Он не нарушает MVVM, потому что в этом случае ваш объект домена является моделью, и у вас есть Presentation.WpfClient.ViewModel.PersonViewModel как ViewModel.
-
Вы можете объединить объект Entity с объектом Domain, если ваш домен Person не имеет сложной бизнес-логики.
Ответ 3
Для вашего первого вопроса использование моделей доменного уровня в качестве моделей MVVM не является нарушением MVVM (См. определение модели здесь)
Подробнее о теме и ответе на ваш второй вопрос см. это: Объекты VS Модели доменов VS Просмотр моделей