Правильный способ проверки ввода

Вопрос:

Каков наиболее эффективный способ проверки ввода?

  1. Как я могу предотвратить наличие вложенных и раздутых операторов if?
  2. Исключает ли правильный способ сделать это? Если нет, какой подход я должен придерживаться?

Плохой пример (я думаю):

public int doSthWithAge(int age)
{
if (age > 0)
{
if (age > 100)
{
throw new AgeIsTooHighException();
}
}
else
{
throw new NoWayException();
}
...
}

Но каковы хорошие пути?

(Если вы дадите какую-либо информацию, относящуюся к языку, сделайте это, как если бы я выполнял проверку в С# -syntax-wise-)

Лучший ответ:

Общим объектно-ориентированным методом проверки является модель ваших правил проверки как объектов первого класса:

  1. Определить общий интерфейс для проверки определенного типа данных
  2. Внедрить набор классов или функций, соответствующих этому интерфейсу
  3. Прокрутите каждую функцию/объект в этой коллекции и вызовите метод проверки. Возвращаемое значение является либо истинным/ложным, либо, возможно, объектом, описывающим сбой проверки (null, если было принято правило проверки). Создайте список отказов валидации, итерации по коллекции правил
  4. Представлять ошибки проверки достоверности для пользователя соответствующим образом

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

Пример:

// 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();

Преимущества этой конструкции:

  • Соответствие интерфейсу будет способствовать согласованности ваших шаблонов кода
  • Один класс или функция в правиле валидации сохраняет ваши правила атомарными, читаемыми, самодокументируемыми, многоразовыми
  • Выполняет принцип единой ответственности для классов правил проверки и помогает упростить код, который должен выполнить проверку
  • Уменьшает циклическую сложность (меньше вложенных операторов if), поскольку это более объектно-ориентированный или функциональный подход, а не процедурный
  • Позволяет вводить инъекции зависимостей для отдельных классов правил проверки, что полезно, если вы обращаетесь к базе данных или классу услуг для проверки

Изменение: @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();
    }
}

Ответ №1

С проверкой эффективности обычно не вызывает беспокойства. Существует два типа проверки, которые вы должны учитывать:

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

Пропуск по любому из них — очень хороший способ закончить либо взломанным, либо плохо сломанным приложением.

Если вы используете ASP.net, есть множество библиотек (в основном из Microsoft), чтобы сделать первый, Anti-XSS lib и т.д.

Последний был бы наиболее эффективно подготовлен в вашей общей бизнес-логике в самих сущностях. EG ваш пользовательский объект не должен допускать возраст -1.

Оцените статью
TechArks.Ru
Добавить комментарий