Чистая проверка архитектуры в домене против уровня сохраняемости данных?

13

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

Однако я по-прежнему борюсь с бизнес-правилами, такими как «сохранить обновления какого-либо элемента, сначала загрузить весь список элементов, на которые у меня есть разрешение на просмотр / редактирование и т. Д., Подтвердить, что этот элемент находится в списке, и что категория элементов в настоящее время не заблокирована для использования ((и другие правила и т. д. и т. п.) ".. потому что это (сложное, но не нетипичное) бизнес-правило, и поэтому оно должно обрабатываться в домене приложения, а не вставлять бизнес-логику в слой дб / персистентность.

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

Без преждевременной оптимизации, каков рекомендуемый подход или некоторые статьи дяди Боба, занимающиеся этим вопросом? Или он скажет: «Проверь в домене, пока это не станет проблемой» ??

Я действительно изо всех сил пытаюсь найти какие-либо хорошие примеры / образцы для чего-либо кроме самых основных вариантов использования.

Обновить:

Привет всем, спасибо за ответы. Я должен был быть более ясным, я писал программное обеспечение (в основном для веб-приложений) в течение долгого времени, и определенно уже испытал и согласился со всеми темами, которые вы коллективно описываете (проверяйте с помощью бэкенда, не доверяйте данным клиента, вообще говоря гоняться за сырой эффективностью только тогда, когда это необходимо, однако признавать сильные стороны инструментов db, когда они доступны, и т. д. и т. д.), и пройти жизненный цикл разработки для разработчиков: «собрать все вместе», чтобы «построить гигантский жирный контроллер с N-уровневыми приложениями», трендами кода и теперь действительно любит и исследует стиль чистой / единой ответственности и т. д., в основном, в результате нескольких проектов, которые недавно превратились в довольно неуклюжие и широко распространенные бизнес-правила по мере развития проектов и выявления новых требований клиентов.

В частности, я рассматриваю архитектуру чистого стиля в контексте создания API REST для клиентских и внутренних функций, где многие бизнес-правила могут быть гораздо более сложными, чем в принципе каждый пример, который вы видите в сети. (даже самими ребятами из Clean / Hex).

Так что, я думаю, я действительно спрашивал (и не смог четко указать), как Clean и API REST будут сидеть вместе, где большинство вещей MVC, которые вы видите в эти дни, имеют валидаторы входящих запросов (например, библиотеку FluentValidation в .NET), но где многие из мои "правила проверки" не так уж и много ", это строка длиной менее 50 символов", но больше "может ли этот пользователь, вызывающий этот пользовательский случай / интерактор, выполнить эту операцию с этим набором данных, учитывая, что некоторый связанный объект в настоящее время заблокирован Team X до позднего месяца и т. д. и т. д. "... те виды глубоко вовлеченных проверок, где применимо МНОЖЕСТВО объектов бизнес-домена и правил домена.

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

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

Но я думаю, что короткий ответ на мой вопрос очень похож на ответ, который я принял: «Это никогда не легко, и это зависит».

Дейл Холбороу
источник
2
Часто есть разница между «правильностью» и «практичностью». Учитывая выбор, который вы предпочитаете?
Роберт Харви
«загрузить весь список элементов» не похоже на бизнес-правило, оно, похоже, слишком углубляется в детали реализации. Если вы можете выполнить правило, используя запрос базы данных, не загружая ничего, почему правило говорит «загрузить»?
Прекратить причинять вред Монике

Ответы:

31

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

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

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

  • Некоторые формы проверки неявны из-за ограничений ввода; например, текстовое поле может разрешить только числовой ввод. Это означает, что у вас может не быть "это числовое значение?" валидатор на странице, но он все равно понадобится где-то на сервере, поскольку ограничения пользовательского интерфейса можно обойти (например, отключив Javascript).

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

  • Уровень пользовательского интерфейса должен выполнять некоторые формы проверки только для преобразования введенных пользователем данных в формат, понятный бизнес-уровню; например, он должен превратить строку «26.06.2017» в объект DateTime в соответствующем часовом поясе.

  • Бизнес-уровень должен выполнять большинство форм проверки, потому что, теоретически, они принадлежат бизнес-уровню.

  • Некоторые формы проверки более эффективны на уровне базы данных, особенно когда необходимы проверки ссылочной целостности (например, чтобы гарантировать, что код состояния находится в списке из 50 допустимых состояний).

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

  • Некоторые формы проверки могут выполняться только сторонними службами, например, при проверке соответствия почтового индекса и названия города.

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

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

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

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

Валидация является частью бизнес-уровня.

Дело в том, что бизнес-логика в DAO сделает недействительной концепцию DAO. Проверка на любом более высоком уровне приведет к избыточной проверке, если вы вызываете бизнес-операции из другого варианта использования.

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

oopexpert
источник
2

Возможно, вы захотите проверить свою точку зрения о том, кто что делает с проверкой. Это БД, где вы знаете, что работаете с БД? Или это сервис (который поддерживается и управляется операциями БД). В моем проекте у каждого агрегатного корня есть список групп, которые могут его прочитать, и список модификаторов. Когда код ищет определенный корень или список корней, которые может видеть пользователь, все детали скрываются за службой, которая принимает идентификатор пользователя, и дополнительными частями контекста поиска, например, где плитка начинается с «бла». Код не заботится о том, что БД выполняет проверку существования, чтобы увидеть, существуют ли группы пользователей в группах читателей. Он просто ожидает список с контентом или без, основанный на том, что когда-либо предоставляет сервис, который определяется только контрактом.

Это относится ко всем слоям. Единообразие валидации является ключом. Поместите как можно больше ваших проверок в домене. Верните ограничения с вашим API. Я в конце не думаю об ограничениях, поступающих из библиотеки X или Z, но из службы.

Virmundi
источник
0

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

JacquesB
источник