Проверка в доменно-управляемом дизайне - PullRequest
0 голосов
/ 19 октября 2018

Наша команда начинает новый проект, следующий за Domain Driven Design (DDD).На высоком уровне у нас есть API в верхней части нашего домена, который позволяет клиенту выполнять операции с доменом.Один из вопросов, которые мне не очень понятны, заключается в том, где мы выполняем проверку определенного свойства / атрибута в DDD.

Рассмотрим этот пример.Допустим, у меня есть нижеприведенный контракт данных / DTO, представленный моим API:

 public class Person
 {
    public string Email { get; set;}
    public string Name { get; set; }
 }

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

Чтобы достичь этого, я вижу следующие три подхода:

В Подход 1 , мы выполняем проверку данных только в API (либо через DataАннотация или свободная проверка).Я не повторяю проверку в моем домене.Теоретически это может означать, что мой домен может перейти в недопустимое состояние.Но, поскольку точка входа (API) проверяется, это невозможно в реальном сценарии.

enter image description here

В Подход 2 , мы делаем проверку данных как в API, так и в моем домене.Этот подход помогает нам полностью удалить связь между моим доменом и API.API может независимо возвращать неверный запрос клиенту.И поскольку домен снова выполняет проверку, нет никакой возможности перехода домена в недопустимое состояние.Однако в этом подходе мы нарушаем принцип СУХОГО.

enter image description here

В Подход 3 , мы проводим проверку только в Домене и не делаемвыполнить проверку на DTO на уровне API.При таком подходе, хотя мы не повторяем проверку, домен не может выдать исключение, когда вызов API пытается перевести его в недопустимое состояние.Скорее, нам нужно было бы обернуть это исключение в некоторый объект Result.Это поможет API отправить соответствующий ответ клиенту (например, неверный запрос вместо внутренней ошибки сервера).Что мне не нравится в этом подходе, так это то, что я предпочел бы бросить жесткое исключение, а не ставить упаковку.enter image description here

Спросите

  • Какой подход наиболее целесообразен и почему?

  • Где проходит грань между бизнес-валидацией и бизнес-правилом?(Предполагая, что бизнес-правило существует в домене.)

  • Есть ли что-то очевидное, чего мне здесь не хватает?

Примечание. Этот вопрос можетвыглядит как Проверка в домене, управляемом дизайном n и , куда следует поместить проверку ввода в домене, управляемом дизайном? , но на самом деле это не отвечает специфике.

Ответы [ 4 ]

0 голосов
/ 30 ноября 2018

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

  • Мы относимся кПроверка API и проверка домена / бизнес-правила как отдельная задача.Мы ставим валидацию API так же, как без DDD.Это потому, что API - это просто интерфейс для общения с нашим Доменом.Завтра у нас может быть промежуточная шина, но логика нашего домена не изменится.Проверки API включают, но не ограничиваются проверками длины полей, проверками регулярных выражений и т. Д.

  • Проверки домена ограничены только бизнес-правилами.Проверки на уровне поля, такие как проверка длины, регулярное выражение и т. Д., Которые ничего не значат для бизнеса, не попадают в бизнес-правила.Если есть нарушение бизнес-правила, мы просто набрасываем DomainException, не заботясь о том, как потребитель с этим справится.В случае ответа API это просто означало бы возврат кода состояния 500 обратно клиенту.

  • Поскольку теперь мы рассматриваем валидацию API и бизнес-правила как отдельную задачу,это означает, что есть вероятность повторения некоторого правила проверки.Но с этим у нас все в порядке, так как это делает вещи намного проще и легче рассуждать.Поскольку они слабо связаны, мы можем легко изменить валидацию API или бизнес-правило независимо друг от друга, не влияя на другие.

  • Существует несколько пограничных случаев, таких как email, где можно утверждать, что ValueObject в нашем Домене.Но мы принимаем это на индивидуальной основе.Например, мы не видим никакого значения, чтобы иметь отдельное поле ValueObject для email в нашем Домене в данный момент.Следовательно, он проверяется (проверка регулярных выражений) только на уровне API.Если в будущем, если в бизнесе появятся дополнительные правила, такие как ограничение в отношении определенного домена, мы можем пересмотреть наше решение.

Приведенные выше принципы помогли нам упростить задачурассуждать о.

0 голосов
/ 19 октября 2018

Теоретически это может означать, что мой домен может перейти в недопустимое состояние.

Я не думаю, что имя длиной более 50 символов будет означать недопустимое состояние домена ...домен по-прежнему будет отлично функционировать.

Необходимо различать проверку входных данных (соответствуют ли данные техническим слотам?) и инварианты домена.Некоторые вещи вы можете проверить на уровне API и не иметь значения для домена, другие должны быть проверены путем загрузки данных домена и, таким образом, не легко доступны для внешних слоев.

Их действительно два (или больше).) различные наборы правил, в большей степени несвязанные, чем вы думаете.

TL; DR - нет жесткого и быстрого ответа.Попробуйте охарактеризовать вещи глубже, чем просто «проверка бизнеса», и мудро выберите подход 1, 2 или 3 в зависимости от типа правила.

0 голосов
/ 19 октября 2018

Какой подход наиболее целесообразен и почему?

Подход 2. Модель предметной области всегда должна выполнять проверку.На прикладном уровне (API) вы можете сделать это или нет, но лучше сделать это, если сможете, так как вы заранее обнаруживаете недействительные данные без необходимости вызова домена.Я говорю «если можете», потому что, возможно, существуют бизнес-правила, которые невозможно проверить без доступа к домену.

ПРИМЕЧАНИЕ. Я следую подходу валидации операций, а не данных.Данные данные могут быть действительными для выполнения операции, но не для других.

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

Я думаю, что вы неправильно понимаете / смешиваете понятия.Понятие «бизнес-правила», а другое понятие «проверка».Валидация - это процесс, который мы проводим для проверки того, соблюдаются ли бизнес-правила или нет.

0 голосов
/ 19 октября 2018

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

Важные моменты, на которые следует обратить вниманиепример

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

Семантически оба эти значения являются просто разновидностями «идентификатора».

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

Так что это может быть очень легко одним из тех мест, где вы заботитесь о границе сообщения, но не в пределахсам домен.

Но это не очень хороший прокси для общего вопроса о том, где может жить валидация.

Сравните этот случай с чем-то вроде суммы вклада - это число, и вы быразумно ожидать, чтобы добавить / вычесть его из других чисел, сравнить его с другими числами и так далее.Там вы можете посмотреть на что-то вроде Integer.MAX и сделать разумный вывод, что ошибка атаки / ввода данных гораздо более вероятна, чем подлинный сценарий использования, что вы полностью исключите эту опцию.

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

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

И поэтому совершенно разумно объявить, что имяполе в сообщении не должно превышать 50 символов, и что поле адреса электронной почты в сообщении соответствует определению addr_spec в RFC 5322 .

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

Но в рамках модели предметной области?если вам не нужно делать предположения о данных, то готово.«Приложение говорит, что это байты? Достаточно хорошо для меня!»

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

Но не так уж много добавочной стоимости, внедряющей модель домена с проверками предварительных условий, которые ему не нужны.

(Опять же, в отличие от amount - модель домена имеетбольшой интерес в выявлении нарушений до того, как они начнут беспорядочно перемещать деньги).

...