2013-07-05 4 views
1

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

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

Дурной пример (я думаю):

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

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

(Если вы будете давать какую-либо информацию для конкретного языка, пожалуйста, сделайте это как если бы я сделать проверку в C# -syntax-Wise-)

+1

Вы не указали, какой язык вы находитесь с помощью. В PHP есть отличный набор [фильтрующих функций] (http://php.net/manual/en/book.filter.php), который сделает все это для вас. На вашей выбранной платформе может быть что-то подобное. –

+0

Достаточно справедливо, позвольте мне изменить вопрос для этого в C# –

+0

Этот вопрос, как и задано, слишком широк, так как есть много действительных ответов http://stackoverflow.com/help/dont-ask – Mgetz

ответ

4

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

  1. Определить общий интерфейс для проверки конкретного типа данных
  2. Реализовать коллекцию классов или функций в соответствии с этим интерфейсом
  3. Прокрутите каждую функцию/объект в этой коллекции и вызовите метод проверки. Возвращаемое значение является либо истинным/ложным, либо, возможно, объектом, описывающим сбой проверки (null, если было принято правило проверки). Составьте список ошибок валидации во время прохождения по коллекции правил
  4. 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(); 
    } 
} 
+1

Вы должны быть осторожны, чтобы не перемещать бизнес-логику в объекты проверки, но это может быть очень заманчиво. – Mgetz

+0

@Mgetz это правда. Ваше упоминание о различии между проверкой ввода и проверкой бизнеса важно, и кое-что, что я только начинаю понимать и узнавать. –

+1

Я должен пересмотреть свое утверждение, хорошо иметь объекты проверки, но объекты проверки бизнеса должны быть вызваны только из объекта, который они помогают проверять. Однако самообучающие свойства обычно проще и проще (только объект может обращаться к сеттерам, поэтому вся проверка выполняется в сеттере), для этого требуется, чтобы экземпляр объекта был отброшен и перезагружен, если валидация не удалась. – Mgetz

3

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

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

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

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

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

+0

Я согласен с тем, но все еще хотят знать, есть ли лучшие способы проверки. Также, пожалуйста, сосредоточьтесь на методах (например, вложенных ifs или Exception) вместо языковых библиотек, спасибо. –

Смежные вопросы