Общий объектно-ориентированный метод для валидации моделировать правила проверки в качестве первого класса объектов:
- Определить общий интерфейс для проверки конкретного типа данных
- Реализовать коллекцию классов или функций в соответствии с этим интерфейсом
- Прокрутите каждую функцию/объект в этой коллекции и вызовите метод проверки. Возвращаемое значение является либо истинным/ложным, либо, возможно, объектом, описывающим сбой проверки (null, если было принято правило проверки). Составьте список ошибок валидации во время прохождения по коллекции правил
- Present неудачи проверки достоверности для пользователя соответствующего образом
Вы увидите эту технику в использовании многих библиотек там.
Пример:
// the entity you want to validate
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
public class ValidationFailure
{
public ValidationFailure(string description) { Description = description; }
public string Description { get; set; }
// perhaps add other properties here if desired
}
// note that this is generic and can be reused for any object to validate
public interface IValidationRule<TEntity>
{
ValidationFailure Test(TEntity entity);
}
public class ValidatesMaxAge : IValidationRule<Person>
{
public ValidationFailure Test(Person entity)
{
if (entity.Age > 100) return new ValidationFailure("Age is too high.");
}
}
public class ValidatesName : IValidationRule<Person>
{
public ValidationFailure Test(Person entity)
{
if (string.IsNullOrWhiteSpace(entity.Name))
return new ValidationFailure("Name is required.");
}
}
// to perform your validation
var rules = new List<IValidationRule> { new ValidatesMaxAge(), new ValidatesName() };
// test each validation rule and collect a list of failures
var failures = rules.Select(rule => rule.Test(person))
.Where(failure => failure != null);
bool isValid = !failures.Any();
Преимущества этой конструкции:
- Соответствие интерфейса будет способствовать согласованности в вашей модели кода
- Один класс или функцию на проверки правило сохраняет ваши правила атомное, читаемый, самодополнительный, многоразовый
- Выполняет принцип единой ответственности для классов правил проверки и помогает simp выделяющие код, который необходимо выполнить проверку
- Сокращает cyclomatic complexity (меньше вложенных
if
заявлений), потому что это более объектно-ориентированный или функциональный подход, а не процедурного
- Позволяет введение dependency injection для отдельных классов правил валидации, что полезно если вы обращаетесь класс базы данных или сервис для проверки
Edit: @Mgetz упоминает проверки ввода против бизнес-проверки, которая также является важным фактором. Приведенный выше подход, основанный на правилах, основан на системе, с которой я работаю каждый день. Мы используем это больше для проверки бизнес-логики в классе обслуживания (это сложная корпоративная система с множеством бизнес-правил), и дизайн хорошо служит нашим целям. Конкретные правила, которые я написал выше, очень просты и больше похожи на проверку ввода. Для проверки ввода я рекомендовал бы более легкий подход к весу и чтобы он не зависел от проверки бизнес-логики, когда это необходимо.
Другая реализация этого проекта состоит в том, чтобы иметь один класс валидатора для каждого объекта и использовать что-то более легкое, например lambdas, для отдельных правил проверки. Это используется, например, популярной библиотекой Fluent Validation. Это очень удобно для проверки пользовательского ввода, так как он позволяет меньше кода, чтобы сделать простую проверку, и призывает вас, чтобы сохранить проверку входных данных отдельно от бизнес-логики проверки:
// Example using the FluentValidation library
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(p => p.Age).LessThan(100);
RuleFor(p => p.Name).NotEmpty();
}
}
Вы не указали, какой язык вы находитесь с помощью. В PHP есть отличный набор [фильтрующих функций] (http://php.net/manual/en/book.filter.php), который сделает все это для вас. На вашей выбранной платформе может быть что-то подобное. –
Достаточно справедливо, позвольте мне изменить вопрос для этого в C# –
Этот вопрос, как и задано, слишком широк, так как есть много действительных ответов http://stackoverflow.com/help/dont-ask – Mgetz