DDD с EF Core (DTO, Бизнес и т. Д.) - PullRequest
1 голос
/ 09 июля 2019

Я пытаюсь войти в Design Patterns и REST API, и для проекта я использую Entity Framework Core с:

  • Шаблон репозитория
  • Единица работы

Некоторые вещи, которые для меня действительно туманны:

  • Проверка данных, где это должно быть сделано?
  • События?Где это должно быть вызвано?Пример. Когда пользователь регистрируется, я хочу отправить ему электронное письмо.
  • Должен ли бизнес-уровень использовать модели DTO или Domain?
  • Куда должно перейти преобразование из моделей DTO в Domain?
  • Что должно входить в контроллер?

Я знаю, что эти вещи также зависят от разработчика, но какой лучший / "оригинальный" способ сделать это.

Ответы [ 2 ]

1 голос
/ 12 июля 2019

Мне нужно заранее извиниться за то, что я не могу дать вам достаточно рецептов, но вот мое мнение по вашему вопросу.

Вы упомянули шаблоны проектирования, но также пометили свой вопрос тегом domain-driven design, поэтому я предполагаю , что вы хотите использовать тактические шаблоны DDD в своем проекте. Я хотел бы подчеркнуть, что DDD - это не набор шаблонов проектирования, не шаблон проектирования или стиль архитектуры, это способ проектирования систем с учетом бизнеса.

В DDD одним из наиболее полезных шаблонов является шаблон Aggregate. Агрегат - это набор объектов, которые образуют границу согласованности, которая содержит достаточно информации для самостоятельного принятия любого бизнес-решения, при условии, что все бизнес-правила для этого набора объектов собраны в одном месте.

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

Теперь я постараюсь разобрать ваши конкретные точки.

Проверка данных, где это должно быть сделано?

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

Когда команда передается службе приложения, она должна гарантировать, что она получает правильное состояние объекта (агрегат) домена, поэтому, по крайней мере, вы проверяете, существует ли объект, пытаясь получить его из вашей базы данных. Вы также можете использовать объекты значений, такие как Email или Address, и создавать их из примитивных типов, передаваемых в качестве свойств команды. Ценные объекты являются идеальным местом для введения некоторых бизнес-правил, и проверка будет происходить естественным образом при попытке их построить.

Последний уровень защиты - это модель вашего домена. На всех предыдущих этапах вы можете быть совершенно уверены, что у вас уже есть допустимые объекты значений и допустимая сущность домена для работы. Агрегат защищает свои инварианты, и по определению не должно быть возможности перевести агрегат в недопустимое состояние. Я обычно не называю это проверка .

События? Где это должно быть вызвано? Пример: когда пользователь зарегистрирован, я хочу отправить ему электронное письмо.

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

Должен ли бизнес-уровень использовать модели DTO или Domain?

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

Куда должно идти преобразование из моделей DTO в домены?

Я бы вообще не стал использовать термин DTO в этом контексте, поскольку состояние вашей сущности можно рассматривать как DTO, а также вашу модель API.и ваше мероприятие.Если вы говорите о своем контракте API, это команда, и она не «конвертируется», ваш API получает команду от API и вызывает модель вашего домена.

Что должно войти вконтроллер?

Контроллеры API - это только край вашего приложения.API заботится о транспорте (HTTP или что-то еще), сериализации, аутентификации и некоторых проблемах авторизации и обработке исключений.Его основная цель - убедиться, что запрос API выглядит корректно и передать его службе приложений.

Если вы ищете пример приложения, использующего WebAPI, EF и реализующего некоторые тактические шаблоны DDD, вы можетехочу посмотреть рабочий образец на Packt repo https://github.com/PacktPublishing/Hands-On-Domain-Driven-Design-with-.NET-Core/tree/master/Chapter09/ef-core

1 голос
/ 09 июля 2019

Проверка данных:

Все проверки должны выполняться как часть уровня домена, как правило, как часть фабричного метода в классе Entity.У вас может быть отдельный фабричный метод или класс, если он вам больше подходит.Важно помнить следующее: объекты Entity / Aggregate должны ВСЕГДА быть действительными.Они не могут находиться в недопустимом состоянии, и вам нужно проверить их действительность с помощью is_valid методов.

Пример рабочего процесса может выглядеть следующим образом:

  • Служба приложений инициализирует хранилище
  • Служба приложений вызывает метод фабрики для сборки сущности
  • Метод фабрики выполняет проверки и проверяет правильность переданных данных
  • Метод фабрики возвращает построенный действительный объект
  • Служба приложений передает объект в хранилище для сохранения.

События :

События должны запускаться как часть уровня домена сразу после бизнес-процесса.логика выполняется.

Чтобы предотвратить преждевременную отправку событий (например, до сохранения данных), в идеале вы должны вызывать события в бизнес-логике, но отправлять их как часть своей единицы работы только послеуспешная постоянная транзакция.

Обработка DTO:

Бизнес-планОн должен принять DTO и вернуть модели Домена.Проверка происходит во время преобразования DTO в модель домена.DTO (или даже аргументы в виде простых ключевых слов) являются правильными входными данными для фабричных методов.

Преобразование из DTO в модель Домена должно происходить в фабричных методах, если создаваемый объект является новым.В случае, если вы имеете дело со сценарием обновления, хранилище извлекает постоянный объект, воссоздает его как сущность домена, используя конструктор объекта, и применяет изменения DTO в явном методе update, который также запускает проверки.

Ответственность контроллера:

Контроллер должен отвечать за:

  • Деконструкция объекта запроса
  • Сборка параметров (даже связанных с сеансомтакие элементы, как текущий вошедший в систему пользователь)
  • Инициализация DTO
  • Вызов соответствующей службы приложений для выполнения

Эти концепции применимы к любому дизайну DDD, включаяEF Core.

...