Hola de nuevo Como parte del lanzamiento del curso para desarrolladores de C #, realizamos una lección abierta tradicional sobre la herramienta de validación fluida . En el seminario web, examinamos cómo deshacerse de un montón de ifs mediante el ejemplo de verificar la exactitud de completar los datos del cliente, estudiamos la implementación interna de la biblioteca y cómo poner en práctica el enfoque de la interfaz fluida. El seminario web fue organizado por Alexei Yagur , jefe de equipo de YouDo.
¿Por qué es necesaria la validación?
Wikipedia
nos dice que la
validación (del lat. Validus "saludable, fuerte, fuerte") es una prueba de que se cumplen los requisitos de un usuario, producto, servicio o sistema en particular. Como regla general, la validación se lleva a cabo según sea necesario, suponiendo tanto un análisis de las condiciones de uso especificadas como una evaluación de la conformidad de las características del producto con los requisitos existentes. El resultado de la validación es la conclusión sobre la posibilidad de usar el producto para condiciones específicas.
En cuanto a la herramienta de
validación fluida , su conocimiento nos permitirá:
- ahorre tiempo al resolver tareas relacionadas con la validación de datos;
- traer cheques caseros dispersos a un solo formulario;
- muestre su conocimiento de la validación del café a sus colegas :)
Pero todo esto es teoría, mejor practiquemos.
Validación de estudio de caso: interactivo
Entonces, la implementación práctica de validación en C # es la siguiente:

Tenemos una clase Cliente, que tiene el conjunto de campos más simple: Nombre - apellido, Apellido - apellido, Edad - edad. Y hay una cierta clase CustomerManager que guarda, como vemos, un nuevo usuario (comprador) en el CustomerRepository y muestra información en la consola que el cliente ha sido agregado con éxito.
Intentemos agregar un personalizado y un administrador que gestionará el personalizado:
void Main() { var customer = new Customer { FirstName = " ", LastName = "", Age = 57, }; var manager = new CustomerManager(); manager.Add(customer); }
El resultado de la ejecución será el resultado en la consola del siguiente texto:
.
Como puedes ver, hasta ahora todo bien. Pero, ¿qué sucede si los datos "en mal estado" aparecen de repente en nuestra base de datos. Por ejemplo, si se ingresa información incorrecta en los campos (número de teléfono en lugar de nombre, edad con un signo menos, etc.):
{ FirstName = "+79123456789", LastName = "valde@mar.ru", Age = -14, };
Como resultado, veremos que también se agregará un medidor personalizado con un conjunto de datos incomprensible:
+79123456789 valde@mar.ru .
Naturalmente, no queremos tener esos datos en nuestro repositorio. ¿Cómo nos protegemos? La opción más fácil es
devolver un error si, por ejemplo, no tenemos todos los caracteres: letras. Para hacer esto, establecemos la condición para FirstName usando if, y si la condición no se cumple, detenemos la función usando return y mostramos el mensaje "Error en nombre" en la consola. Hacemos lo mismo con LastName. En cuanto a la edad, aquí verificamos el rango de números, por ejemplo:
if (customer.Age < 14 || customer.Age > 180)
Ahora supongamos que
necesitamos agregar campos adicionales para el comprador , por ejemplo, un teléfono. Validaremos el teléfono con la condición de que los valores ingresados deben comenzar con "+79" e incluir solo números. Todo esto en sí mismo será un diseño bastante engorroso, pero si queremos agregar más correos electrónicos.
De todos modos, después de realizar las operaciones anteriores, obtenemos un
montón de ifs y una gran hoja de código . Para un desarrollador externo no será fácil comprender dicho código. Que hacer
Conexión de validación fluida
LINQPad tiene la capacidad de conectar la biblioteca de validación fluida,
lo que hacemos . Además, creamos otra clase CustomerValidator, que será un validador. En consecuencia, prescribimos todas las reglas necesarias en él. Hacemos ajustes adicionales y eliminamos los numerosos ifs, porque ya no son necesarios.
Como resultado, nuestro código final se verá así:
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); } }
Y un poco mas de teoria
Me gustaría agregar algunas palabras sobre la validación fluida. Esta herramienta se llama así debido a la interfaz "fluida". Nuevamente, Wikipedia
nos dice que la interfaz fluida es una forma de implementar una API orientada a objetos, con el objetivo de aumentar la legibilidad del código fuente del programa. La definición, como vemos, contiene muchas palabras hermosas y largas, que no siempre son claras. Pero podemos decir lo contrario:
"Una interfaz fluida es una forma de implementar una API orientada a objetos en la que los métodos devuelven la misma interfaz en la que fueron llamados".
Alexey Yagur
En cuanto a la biblioteca en sí, incluye los siguientes
componentes :
- La lógica básica Aquí hay un enlace a GitHub donde puedes ver la lógica principal.
- Lógica auxiliar . FluentValidation.ValidatorAttribute es responsable de esta lógica.
- Parte sensible al contexto . Ver FluentValidation.AspNetCore , FluentValidation.Mvc5 y FluentValidation.WebApi .
- Pruebas En consecuencia, estamos interesados en FluentValidation.Tests.AspNetCore , FluentValidation.Tests.Mvc5 , FluentValidation.Tests.WebApi y FluentValidation.Tests .
Eso es todo, paso a paso para escribir el código, ver el
video . Además, puede estar interesado en interactivos adicionales sobre el tema
"Variables en textos de error" , que el profesor realizó cerca del final del seminario web.
¡Nos vemos en el curso para
desarrolladores de C # !