DDD принципы и репозитории с Dapper - PullRequest
0 голосов
/ 02 февраля 2019

Я настраиваю решение, в котором я применяю луковую архитектуру и шаблоны DDD.

Один из принципов DDD поощряет доменные объекты иметь только частные установщики и частный конструктор по умолчанию, чтобы убедиться, что вы не можетесоздать сущности домена в недопустимом состоянии.

Репозитории содержат операции с данными над сущностями домена, которые отображаются в базу данных или из нее.Я пробовал следующие два подхода:

  1. Доменные сущности в чистом виде: нет конструктора по умолчанию, нет открытых сеттеров;проверка выполняется в конструкторе (ах);что гарантирует, что вы не можете создать объект домена в недопустимом состоянии.Побочный эффект заключается в том, что их труднее дематериализовать в репозиториях при операциях чтения;как вам нужно отражение, чтобы иметь возможность создавать экземпляры и свойства карты;и использование динамики в Dapper запросах, которые должны быть сопоставлены с фактическими объектами домена.Если бы я сопоставил это непосредственно с сущностями домена без использования динамики, Dapper выдает исключение, что нет открытого конструктора .

  2. сущности домена в не-purist way: вы разрешаете конструктор по умолчанию, и все сеттеры являются открытыми;Таким образом, вы можете создавать объекты, которые не являются действительными в данный момент времени.В этом случае вам нужно вызвать метод Validate () вручную, чтобы убедиться, что они действительны, прежде чем продолжить.Это значительно облегчает дематериализацию в репозиториях, так как вам не нужно отражений или динамики для сопоставления базы данных с моделью.

Оба метода работают, однако с вариантом 2 репозитории становятсянамного проще, потому что они содержат намного меньше пользовательского кода отображения и без отражения, очевидно, будут также более производительными.Конечно, DDD не применяется по-пуристски.

Прежде чем решить, что я буду использовать в своем проекте, вопрос: существуют ли какие-либо другие микро-ORM-фреймворки , которые могутобрабатывать частные конструкторы и сеттеры, так что сопоставление базы данных с такими «чистыми» объектами домена поддерживается без дополнительной пользовательской логики сопоставления?(Ни EF, ни NHibernate, я хочу что-то легкое).

Или другие технические решения для сохранения «чистого» подхода к объектам модели в сочетании с простым отображением репозитория?

РЕДАКТИРОВАТЬ: решение, которое я реализовал, было следующим.

Во-первых, все конструкторы и установщики в объектах домена являются «внутренними», что означает, что они не могут быть установлены потребителями модели домена.Тем не менее, я использую InternalsVisibleTo, чтобы позволить слою доступа к данным напрямую обращаться к ним, так что это означает, что дематериализация из базы данных очень проста с Dapper (нет необходимости в промежуточных моделях).На уровне приложения я могу использовать только доменные методы для изменения сущности домена, а не свойства напрямую.

Во-вторых, для создания новых внутренних объектов из моего уровня приложений я добавил беглых компоновщиков, чтобы помочь в создании сущностей домена,поэтому теперь я могу построить их следующим образом:

 User user = new UserBuilder()
        .WithSubjectId("045454857451245")
        .WithDisplayName("Bobby Vinton")
        .WithLinkedAccount("Facebook", la => la.WithProviderSubjectId("1548787788877").WithEmailAddress("bobby1@gmail.com"))
        .WithLinkedAccount("Microsoft", la => la.WithProviderSubjectId("54546545646").WithEmailAddress("bobby2@gmail.com"))

Когда построитель «строит» сущность, проверка также выполняется, поэтому вы никогда не сможете создать сущность в недопустимом состоянии.

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Один из принципов DDD призывает доменные сущности иметь только частные установщики и частный конструктор по умолчанию, чтобы убедиться, что вы не можете создавать доменные сущности в недопустимом состоянии.

Это не совсемправо.Да, модели с расширенным доменом обычно не предоставляют сеттеры, но это потому, что им не нужны сеттеры .Вы говорите модели, что делать на более высоком уровне абстракции, и позволяете ей определять, как ее собственные структуры данных должны быть изменены.

Аналогично, есть часто случаев, когда это имеет смыслпредставить конструктор по умолчанию: если вы думаете о агрегате как о конечном автомате, то конструктор по умолчанию - это способ инициализации агрегата в его состоянии «запуска».

Так что обычно вы воссоздаете агрегат в одномдвумя способами: либо вы инициализируете его в состоянии по умолчанию, а затем отправляете ему кучу сообщений, либо используете шаблон Factory, как описано в синей книге.

это означаетдополнительное сопоставление между ними, что делает код более сложным

Возможно, но это также гарантирует, что код вашего домена меньше зависит от магии ORM.В частности, это означает, что логика вашего домена может работать с другой структурой данных, чем та, которая используется для упрощения персистентности.

Но это не бесплатно - у вас естьописать в коде, как получать значения из совокупного корня и обратно в базу данных (или в сущность ORM, выступая в качестве прокси для базы данных).

0 голосов
/ 02 февраля 2019

Ключ в том, что вы не используете Dapper для работы с вашими доменными сущностями, но вместо этого вы используете его внутри своего уровня хранилища с сущностями POCO.Ваши методы хранилища будут возвращать сущности Домена путем преобразования сущностей POCO (которые Dapper использует для доступа к данным) в сущности Домена.

...