Olá novamente! Como parte do lançamento do curso de desenvolvedor de C #, realizamos uma aula tradicional aberta sobre a ferramenta Validação de Fluente . No webinar, examinamos como se livrar de vários ifs usando um exemplo de verificação da correção do preenchimento de dados do cliente, estudamos a implementação interna da biblioteca e como colocar em prática a abordagem da Interface Fluente. O webinar foi organizado por Alexei Yagur , líder de equipe da YouDo.
Por que a validação é necessária?
A Wikipedia
nos diz que a
validação (da lat. Validus “saudável, forte, forte”) é a prova de que os requisitos de um usuário, produto, serviço ou sistema específico são atendidos. Como regra, a validação é realizada conforme necessário, assumindo uma análise das condições de uso especificadas e uma avaliação da conformidade das características do produto com os requisitos existentes. O resultado da validação é a conclusão sobre a possibilidade de usar o produto para condições específicas.
Quanto à ferramenta
Validação Fluente , seu conhecimento nos permitirá:
- economize tempo ao resolver tarefas relacionadas à validação de dados;
- levar cheques caseiros dispersos para um único formulário;
- mostre seu conhecimento sobre validação de café aos colegas :)
Mas isso é tudo teoria, é melhor começarmos a praticar.
Validação de Estudo de Caso: Interativo
Portanto, a implementação prática da validação em C # é a seguinte:

Temos uma classe Customer, que possui o conjunto mais simples de campos: Nome - sobrenome, Sobrenome - sobrenome, Idade - idade. E há uma certa classe CustomerManager que salva, como vemos, um novo usuário (comprador) no CustomerRepository e exibe informações no console que o cliente foi adicionado com êxito.
Vamos tentar adicionar um personalizado e um gerente que gerenciará o personalizado:
void Main() { var customer = new Customer { FirstName = " ", LastName = "", Age = 57, }; var manager = new CustomerManager(); manager.Add(customer); }
O resultado será a saída do seguinte texto no console:
.
Como você pode ver, até agora tudo bem. Mas o que acontece se dados "estragados" aparecerem repentinamente em nosso banco de dados. Por exemplo, se informações incorretas forem inseridas nos campos (número de telefone em vez de nome, idade com um sinal de menos, etc.):
{ FirstName = "+79123456789", LastName = "valde@mar.ru", Age = -14, };
Como resultado, veremos que um medidor personalizado com um conjunto de dados incompreensível também será adicionado:
+79123456789 valde@mar.ru .
Naturalmente, não queremos ter esses dados em nosso repositório. Como nos protegemos? A opção mais fácil é
retornar um erro se, por exemplo, não tivermos todos os caracteres - letras. Para fazer isso, definimos a condição para FirstName usando if e, se a condição não for atendida, paramos a função usando return e exibimos a mensagem “Erro no nome” no console. Fazemos o mesmo com Sobrenome. Quanto à idade, aqui verificamos o intervalo de números, por exemplo:
if (customer.Age < 14 || customer.Age > 180)
Agora vamos supor que
precisamos adicionar campos adicionais para o comprador , por exemplo, um telefone. Validaremos o telefone usando a condição de que os valores inseridos devem começar com "+79" e incluir apenas números. Tudo isso por si só será um design bastante complicado, mas se quisermos adicionar mais e-mail?
De qualquer forma, depois de executar as operações acima, temos um
monte de ifs e uma grande folha de código . Não será fácil para um desenvolvedor externo entender esse código. O que fazer?
Conexão da validação fluente
O LINQPad tem a capacidade de conectar a biblioteca de Validação Fluente, o
que fazemos . Além disso, criamos outra classe CustomerValidator, que será um validador. Assim, prescrevemos todas as regras necessárias. Fazemos ajustes adicionais e removemos os vários ifs, porque eles não são mais necessários.
Como resultado, nosso código final ficará assim:
void Main() { var customer = new Customer { FirstName = "Alex2", LastName = "Petrov1", Age = 10, Phone = "+791234567893", Email = "adsf@fadsf3.com" }; var manager = new CustomerManager(); manager.Add(customer); } class Customer { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public string Phone { get; set; } public string Email { get; set; } } class CustomerManager { CustomerRepository _repository; CustomerValidator _validator; public CustomerManager() { _repository = new CustomerRepository(); _validator = new CustomerValidator(); } public void Add(Customer customer) { if (!ValidateCustomer(customer)) { return; } _repository.Add(customer); Console.WriteLine($" {customer.FirstName} {customer.LastName} ."); } private bool ValidateCustomer(Customer customer) { var result = _validator.Validate(customer); if (result.IsValid) { return true; } foreach(var error in result.Errors) { Console.WriteLine(error.ErrorMessage); } return false; } } class CustomerValidator : AbstractValidator<Customer> { public CustomerValidator() { var msg = " {PropertyName}: {PropertyValue}"; RuleFor(c => c.FirstName) .Must(c => c.All(Char.IsLetter)).WithMessage(msg); RuleFor(c => c.LastName) .Must(c => c.All(Char.IsLetter)).WithMessage(msg); RuleFor(c => c.Age) .GreaterThan(14).WithMessage(msg) .LessThan(180).WithMessage(msg); RuleFor(c => c.Phone) .Must(IsPhoneValid).WithMessage(msg) .Length(12).WithMessage(" {MinLength} {MaxLength}. : {TotalLength}"); RuleFor(c => c.Email) .NotNull().WithMessage(msg) .EmailAddress(); } private bool IsPhoneValid(string phone) { return !(!phone.StartsWith("+79") || !phone.Substring(1).All(c => Char.IsDigit(c))); } } class CustomerRepository { Random _random; public CustomerRepository() { _random = new Random(); } public void Add(Customer customer) { var sleepInSeconds = _random.Next(2, 7); Thread.Sleep(1000 * sleepInSeconds); } }
E um pouco mais de teoria
Gostaria de acrescentar algumas palavras sobre a validação fluente. Essa ferramenta é chamada dessa maneira devido à interface "fluida". Novamente, a Wikipedia
nos diz que a interface fluida é uma maneira de implementar uma API orientada a objetos, com o objetivo de aumentar a legibilidade do código-fonte do programa. A definição, como vemos, contém muitas palavras bonitas e longas, o que nem sempre é claro. Mas podemos dizer o contrário:
"Uma interface fluida é uma maneira de implementar uma API orientada a objetos, na qual os métodos retornam a mesma interface na qual foram chamados".
Alexey Yagur
Quanto à própria biblioteca, ela inclui os seguintes
componentes :
- A lógica básica . Aqui está um link para o GitHub, onde você pode ver a lógica principal.
- Lógica auxiliar . FluentValidation.ValidatorAttribute é responsável por essa lógica.
- Parte sensível ao contexto . Consulte FluentValidation.AspNetCore , FluentValidation.Mvc5 e FluentValidation.WebApi .
- Testes . Portanto, estamos interessados em FluentValidation.Tests.AspNetCore , FluentValidation.Tests.Mvc5 , FluentValidation.Tests.WebApi e FluentValidation.Tests .
Isso é tudo, passo a passo para escrever código, veja o
vídeo . Além disso, você pode estar interessado em interações adicionais sobre o tópico
"Variáveis nos textos de erro" , que o professor realizou próximo ao final do seminário on-line.
Vejo você no Curso de
Desenvolvedor C # !