Comments 24
Тема сложная, но очень полезная.
Двойная валидация это всегда хорошо, и если есть даже сухие статьи на эту тему, которые могли бы упростить — это хорошо.
Двойная валидация это всегда хорошо, и если есть даже сухие статьи на эту тему, которые могли бы упростить — это хорошо.
Два вопроса.
Первый: чем FluentValidator лучше, чем валидация на основе атрибутов DataAnnotations?
Второй: вы знаете, когда выполняется валидатор, определенный атрибутом на классе, и почему в нем не следует задавать правила для отдельных свойств?
Первый: чем FluentValidator лучше, чем валидация на основе атрибутов DataAnnotations?
Второй: вы знаете, когда выполняется валидатор, определенный атрибутом на классе, и почему в нем не следует задавать правила для отдельных свойств?
1) всё в одном месте; сложный код проверки тоже в одном месте; делает «более чистые» классы модели (не загрязненные атрибутами); проще для юнит тестирования; поддержка не только asp.net mvc
наверно это не всё…
наверно это не всё…
«делает «более чистые» классы модели (не загрязненные атрибутами);»
Во-первых, атрибут все равно есть. Во-вторых, почему валидационный атрибут загрязняет модель, если он описывает ее бизнес-ограничения?
«проще для юнит тестирования»
Что именно вы хотите протестировать?
«поддержка не только asp.net mvc»
DataAnnotations тоже поддерживаются не только в asp.net mvc.
Во-первых, атрибут все равно есть. Во-вторых, почему валидационный атрибут загрязняет модель, если он описывает ее бизнес-ограничения?
«проще для юнит тестирования»
Что именно вы хотите протестировать?
«поддержка не только asp.net mvc»
DataAnnotations тоже поддерживаются не только в asp.net mvc.
«можно и без атрибута. Модель может быть использована не один раз и в разных бизнес сценариях — откуда может быть разные правила валидации её.»
Вот только в посте об этом ни слова вообще. Спасибо.
«Протестировать валидацию собственно. Пример из офиц. доки.»
Ну, эта проблема распадается на две.
Первое — тестирование кастомной валидации. Это в DataAnnotations делается так же, потому что это отдельный атрибут. Поставляемую «из коробки» валидацию не тестируют, это бессмысленно.
И второе — это тестирование того, привязана ли нужная валидация к конкретному юз-кейсу. В этом случае тестирование для FV и для DA одинаковое — мы вызываем юз-кейс и смотрим, вернул ли он нам ошибки.
Вот только в посте об этом ни слова вообще. Спасибо.
«Протестировать валидацию собственно. Пример из офиц. доки.»
Ну, эта проблема распадается на две.
Первое — тестирование кастомной валидации. Это в DataAnnotations делается так же, потому что это отдельный атрибут. Поставляемую «из коробки» валидацию не тестируют, это бессмысленно.
И второе — это тестирование того, привязана ли нужная валидация к конкретному юз-кейсу. В этом случае тестирование для FV и для DA одинаковое — мы вызываем юз-кейс и смотрим, вернул ли он нам ошибки.
В статье я только поверхностно коснулся того, что такое FV.
По поводу тестирования атрибутов — это отельный вопрос. Мне нужно было для валидации получать данные из БД. Замокать логику доступа к данным в атрибуте в юнит тестах довольно сложно, потому что это метаданные класса, нельзя использовать наследование или заменить атрибут во время выполнения. С FV это делается очень просто.
По поводу тестирования атрибутов — это отельный вопрос. Мне нужно было для валидации получать данные из БД. Замокать логику доступа к данным в атрибуте в юнит тестах довольно сложно, потому что это метаданные класса, нельзя использовать наследование или заменить атрибут во время выполнения. С FV это делается очень просто.
«В статье я только поверхностно коснулся того, что такое FV.»
Именно поэтому я и спросил, чем он лучше DataAnnotations.
«Мне нужно было для валидации получать данные из БД. Замокать логику доступа к данным в атрибуте в юнит тестах довольно сложно, потому что это метаданные класса, нельзя использовать наследование или заменить атрибут во время выполнения. С FV это делается очень просто. „
В вашем примере тоже атрибут. К нему применимы все ограничения по тестированию, которые применимы к DataAnnotations. Ну и нет ничего сложного замокать логику доступа к данным в атрибуте, поскольку атрибут — это такой же код, как и все остальное, вынесите данные в сервис и обратитесь к нему через сервис-локатор.
Именно поэтому я и спросил, чем он лучше DataAnnotations.
«Мне нужно было для валидации получать данные из БД. Замокать логику доступа к данным в атрибуте в юнит тестах довольно сложно, потому что это метаданные класса, нельзя использовать наследование или заменить атрибут во время выполнения. С FV это делается очень просто. „
В вашем примере тоже атрибут. К нему применимы все ограничения по тестированию, которые применимы к DataAnnotations. Ну и нет ничего сложного замокать логику доступа к данным в атрибуте, поскольку атрибут — это такой же код, как и все остальное, вынесите данные в сервис и обратитесь к нему через сервис-локатор.
вынесите данные в сервис и обратитесь к нему через сервис-локатор
Я почитал немного про сервис-локаторы. Можно небольшой пример как передать атрибуту именно локатор, у которого он может получить сервис?
Я вижу проблему в том, что при каждом обращении к атрибуту объекта через рефлексию создается новый экземпляр атрибута, поэтому вариант с установкой локатора через сеттер свойства не подходит.
С другой стороны задать конкретный локатор в конструкторе мы не может т.к. там должна быть либо константа времени компиляции либо тип.
Я что-то упускаю или не правильно понял реализацию сервис-локатора?
«Я почитал немного про сервис-локаторы. Можно небольшой пример как передать атрибуту именно локатор, у которого он может получить сервис?»
Эээ… сервис-локатор никуда не передается, он глобальный. В этом, собственно, весь пойнт.
Эээ… сервис-локатор никуда не передается, он глобальный. В этом, собственно, весь пойнт.
Какое-то статическое свойство какого-то класса? А как его в таком случае фейкать при тестировании?
Чуток погуглив нашел вопрос на stackoverflow. Видимо, фейкать нужно как раз свойство DependencyInjector.Current.
Да, теперь понятнее, а то не складывалась картинка, не хватало пазла, спасибо =)
Чуток погуглив нашел вопрос на stackoverflow. Видимо, фейкать нужно как раз свойство DependencyInjector.Current.
Да, теперь понятнее, а то не складывалась картинка, не хватало пазла, спасибо =)
> Модель может быть использована не один раз и в разных бизнес сценариях
Можно пример? Если это модель из нескольких свойств, то проще создать заново. А если что-то большое, то это как правило специфическое и повтороное использование без изменений сомнительно.
В этом контексте разделение валидации и модели (а валидация по сути часть бизнес-логики), мне кажется сомнительным удовольствием. Исключение — специфические для UI (или других, кроме BL, слоев) атрибуты.
Можно пример? Если это модель из нескольких свойств, то проще создать заново. А если что-то большое, то это как правило специфическое и повтороное использование без изменений сомнительно.
В этом контексте разделение валидации и модели (а валидация по сути часть бизнес-логики), мне кажется сомнительным удовольствием. Исключение — специфические для UI (или других, кроме BL, слоев) атрибуты.
Об исключениях и идет речь.
Как бы вы стали делать валидацию такого «сценария» (да и чтобы писанины было поменьше рутинной): два юзера: простой и супер. Что-то покупают, указывая количество. Первому можно «до 10 штук» купить, второму «до 20 штук»?
Как бы вы стали делать валидацию такого «сценария» (да и чтобы писанины было поменьше рутинной): два юзера: простой и супер. Что-то покупают, указывая количество. Первому можно «до 10 штук» купить, второму «до 20 штук»?
Если в модели для каждого свойства заданы несколько атрибутов для валидации (обязательность, длина, регулярное выражение, какой-то кастомный, например) — модель превращается у «ужасного монстра». А если добавить еще и локализацию — то сложно будет разглядеть свойства под навешанными атрибутами.
При FV добавляется всего один атрибут класса и вся логика находится в нем. Модель становится намного легче и понятнее.
При FV добавляется всего один атрибут класса и вся логика находится в нем. Модель становится намного легче и понятнее.
«Если в модели для каждого свойства заданы несколько атрибутов для валидации (обязательность, длина, регулярное выражение, какой-то кастомный, например) — модель превращается у «ужасного монстра».»
Зато при взгляде на модель сразу видны наложенные на нее бизнес-правила.
«Модель становится намного легче и понятнее. „
Легче — да. Понятнее? Нет, потому что мы перестаем видеть бизнес-правила.
Зато при взгляде на модель сразу видны наложенные на нее бизнес-правила.
«Модель становится намного легче и понятнее. „
Легче — да. Понятнее? Нет, потому что мы перестаем видеть бизнес-правила.
Понятнее? Нет, потому что мы перестаем видеть бизнес-правила.
В студии довольно просто перейти к определению класса атрибута и посмотреть бизнес-правила. Тут, наверное, кому как удобнее. Мне было сложно визуально выделять атрибуты валидиции, особенно условные с зависимостями на другие свойства. Они было громоздкие.
Для простых правил DA мне тоже отлично подходит.
«В студии довольно просто перейти к определению класса атрибута и посмотреть бизнес-правила.»
Когда вы смотрите на обращение к свойству объекта где-то по месту его использования? Надо сначала перейти на определение класса (что само по себе не одно действие), а потом на определение атрибута. А для конкретных атрибутов на свойстве достаточно всплывающей подсказки, показывающей атрибуты.
Когда вы смотрите на обращение к свойству объекта где-то по месту его использования? Надо сначала перейти на определение класса (что само по себе не одно действие), а потом на определение атрибута. А для конкретных атрибутов на свойстве достаточно всплывающей подсказки, показывающей атрибуты.
когда выполняется валидатор, определенный атрибутом на классе
Для MVC при байндинге модели, так же как и DA.
почему в нем не следует задавать правила для отдельных свойств
Не совсем понял вопрос. Но столкнулся с ситацией когда определен DA атрибут [Required] и FV NotEmpty() при построении представления происходило исключение связанное с тем, что для свойства одно и тоже правило было задано несколько раз.
А, все, я посмотрел в документацию. Вы пропустили один маааааленький момент: чтобы все это работало, надо еще не забыть зарегистрировать собственную фабрику валидаторов FV: FluentValidationModelValidatorProvider.Configure();
Вопрос про «время срабатывания» снимается (хотя я все-таки рекомендую посмотреть, как DA обрабатывает такие ситуации, это… поучительно).
Вопрос про «время срабатывания» снимается (хотя я все-таки рекомендую посмотреть, как DA обрабатывает такие ситуации, это… поучительно).
зарегистрировать собственную фабрику валидаторов FV: FluentValidationModelValidatorProvider.Configure();
Упустил этот момент, спасибо.
рекомендую посмотреть, как DA обрабатывает такие ситуации
Не до конца понял какие именно ситуации. Можно ссылочку где это можно посмотреть?
Sign up to leave a comment.
ASP.NET MVC: Условная валидация на клиенте с использованием FluentValidation