What is the most efficient way to check an input?
Bad example (I think):
public int doSthWithAge(int age)
{
if (age > 0)
{
if (age > 100)
{
throw new AgeIsTooHighException();
}
}
else
{
throw new NoWayException();
}
...
}
But what are the good ways?
(If you'll give any language-specific information, please do it as if I do the validation in C# -syntax-wise-)
A common object-oriented technique for validation is model your validation rules as first-class objects:
You'll see this technique in use by many libraries out there.
Example:
// 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();
Advantages of this design:
if
statements), because it's a more object-oriented or functional approach rather than procedural Edit : @Mgetz mentions input validation vs business validation, which is also an important consideration. The class-per-rule approach described above is based on a system I work with every day. We use this more for business logic validation within a service class (it's a complex enterprise system with lots of business rules), and the design serves our purposes well. The specific rules I wrote above are very simple and do look more like input validation. For input validation, I'd recommend a lighter weight approach and to keep it separate from business logic validation when appropriate.
Another implementation of this design is to have a single validator class per entity, and use something more lightweight such as lambdas for individual validation rules. This is used by the popular Fluent Validation library, for example. This is great for user input validation, as it allows for less code to do simple validation, and encourages you to keep the input validation separate from the business logic validation:
// Example using the FluentValidation library
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(p => p.Age).LessThan(100);
RuleFor(p => p.Name).NotEmpty();
}
}
With validation efficiency is not usually the concern. There are two types of validation that you should be concerned with:
Skipping over either of these is a very very good way to end up with either a hacked or badly broken application.
If you're using ASP.net there are a plethora of libraries (mostly from Microsoft) to do the former, Anti-XSS lib etc.
The latter would be most efficiently preformed in your shared business logic in the entities themselves. EG your user entity should not allow an age of -1.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.