How you validate your models in your code?

How many times have you come across the typical code full of If's to validate a model?

On several occasions, working on different projects, I have encountered an abuse of if statement to perform different validations of an entity model or a Dto model.

We are talking about the typical structure as for example in c# code

if(string.IsNullOrEmpty(personDto.Name))
{
    thow new Exception("Name can not be empty")	
}

if(personDto.Age < 0 )
{
    thow new Exception("Age range have to between 0 and 100")	
}

......        

Why not use other approaches in which on the one hand we have a cleaner and more maintainable code and on the other hand we avoid launching exceptions where for these cases we have a cost that has a performance cost.

We can use fantastic libraries like FluentValidation

that allows us to perform this type of validation by performing a fully declarative configuration.

In my case I've chosen as a proof of concept to create my own library inspired by FluentValidation using Builder design pattern and Expressions

Example of how to make a configuration to define the validation rules of a model.

internal sealed class PersonValidatorRulesSpecification : IValidatorRulesSpecification<Person> {
    public IRulesValidator<Person> GetRulesValidator() {
        var entityValidatorRules = RulesValidatorBuilder<Person>
            .Create()
            .AddRule(
                ruleName: "NameStartWithJ",
                condition: person => person.Name.StartsWith("j"),
                failedValidationMessage: "Person Name must start with J")
            .AddRule(
                ruleName: "PersonLimitAge",
                condition: person => person.Age > 40,
                failedValidationMessage: "Age must be more than 40")
            .Build();

        return entityValidatorRules;
    }
}        

The use of this library in a console application should be

using ConsoleApp.Specifications;
using Jcc.ValidatorBuilder.Interfaces;
using Microsoft.Extensions.DependencyInjection;

var serviceProvider = new ServiceCollection()
    .AddScoped<IValidatorRulesSpecification<Person>, PersonValidatorRulesSpecification>()
    .BuildServiceProvider();

var service = serviceProvider
    .GetService<IValidatorRulesSpecification<Person>>();

var validator = service.GetRulesValidator();

Person[] persons = [
    new Person("Peter", 41, "street example"),
    new Person("Pepe", 30, "street example 2"),
    new Person("John", 25, "street example 3")
];

foreach (var person in persons) {
      var personValidation = validator.Validate(person);
    Console.WriteLine($" person with name: ${person.Name} - is valid: {personValidation.IsValid}");

    foreach (var rulesErrorMessage in personValidation.FailedErrorMessages) {
        Console.WriteLine($" \t rule name: {rulesErrorMessage.Key} - ruleErrorMessage: {rulesErrorMessage.Value}");
    }
}

Console.Read();

------
public record Person(string Name, int Age, string Address);
        

You can find this example in my github account

What kind of approaches do you prefer in your model's validations?



要查看或添加评论,请登录

社区洞察

其他会员也浏览了