08-05-2007

Validadores

Validacion es un proceso que es necesario en cualquier tipo de software.
A momento de desarrollar un sistemilla en .NET no pude encontrar ninguna herramienta que facilite el uso de definiciones sobre objetos de ciertas condiciones requeridas, antes de ejecutar algun proceso con los objeto de forma comoda, hasta hace un par de semanas: Castle.Core.Validations.

CastleProject es un proyecto espectacular, que provee de una serie componentes modernos a desarrolladores en la plataforma .NET, tales como AOP (programacion oriendata al aspecto) o Container (Microkernel, DI, Inyeccion de dependencias).

Hace como 6 meses que no sacan un nuevo beta de su proxima version 1.0, y me acorde de ellos :)
Husmie en un snapshot y encontre el componenterijillo...
La verdad no es nada del otro mundo, pero esta super util :P

Comunmente se le llama "objetos de negocio" a un grupo de objetos que guardan información valiosa sobre/con los cuales de hacen los procesos del sistema, tanto internos como de comunicación.

La mision es simple: validar que ciertas condiciones, necesarias, se cumplan y esten presentes en un objeto de negocio, antes de "meterlos a la jugera".
A nadie le gustan los jugos hechos con frutas podridas.. :P

Contexto:

//En la cocina podria haber un Cheff, juguera vaso, y naranjas.
Cheff cheff = new Cheff();
Juguera juguera = new Juguera();
Vaso vasoDeJugo = new Vaso();
List naranjas = BolsaDeHilo(41);

//El cheff toma las naranjas
cheff.Manos = naranjas;

//Las inspecciona
cheff.Inspeccionar(); (*)

//Usa la jugera
cheff.Herramienta = juguera;

//Hace el jugo.
vasoDeJugo = cheff.Procesar();



Luego de que el "Cheff" toma en sus manos las naranjas, las inspecciona.


El Cheff no es experto en naranjas, lo unico que sabe es mirar la naranja y observar un par de atributos para descidir si es apta o no para el proceso que continua.
Es aqui (*) donde se hace la validacion:

public void Inspeccionar()
{
foreach (Naranja naranja in manos)
if ( !validador.IsValid(naranja) )
throw new ApplicationException(
string.Format("Naranja invalida: {0}", runner.GetErrorSummary(n).ErrorMessages)
);
}


Para cada naranja, vemos si es valida. Tal cual.

La definicion de las condiciones que debe cumplir una naranja, puede hacerse (o no) de manera acoplada, por ejemplo

[ValidateNotSameValueAttribute(true)]
public bool Podrida
{
get { return podrida; }
set { podrida = value;}
}



Si una naranja esta podrida, entonces la validacion cortara el flujo de ejecucion con una Escepcion:

Unhandled Exception: System.ApplicationException: Naranja invalida: Field must not equals 'False'
at JugoNaranjas.Cheff.Inspeccionar () [0x0002a] in /home/killfill/Projects/JugoNaranjas/JugoNaranjas/Cheff.cs:23


otro ejemplo podria ser:

[ValidateEmailAttribute("huh?")]
public string Comprador
{
get { return comprador; }
set { comprador = value;}
}



Si el atributo "Comprador" de una naranja no es un correo, la escepcion sera:

Naranja invalida: huh?


Hay un par de validadores (Validate*) simples ya echos, pero podriamos perfectamente hacer uno especial:

public class ValidadorColor : AbstractValidator
{
public override bool IsValid (object o, object fieldValue)
{
return ((Naranja) o).Color != "verde";
}

public override bool SupportsWebValidation {
get { return true; }
}
}


Donde se define que si la naranja no es verde, entonces no esta buena...
(De pasadita habilitamos el uso Web)

Para poder usar esta definicion directamente en una Naranja, se debe hacer un Atributo, a modo de Adaptador a esta nueva validacion

public class ValidaColorAttribute : Castle.Components.Validator.AbstractValidationAttribute
{
public ValidaColorAttribute() : base("Las naranjas verdes son acidas...")
{}

public override IValidator Build()
{
IValidator validator = new ValidadorColor();
ConfigureValidatorMessage(validator);
return validator;
}
}


Sin entrar en mas detalles, aqui de define el mensaje de excepcion, y se escribe el metodo Build, que el componente usa para obtener en validador que le corresponde al atributo.


El atributo se usaria igual que los otros...

[ValidadaColor]
public string Color
{
get { return color; }
set { color = value;}
}



Con eso, nos aseguramos que el jugo no quede acido, pues si hay una naranja verde, obtendriamos:

"Naranja invalida: Las naranjas verdes son acidas..."




saludos.