viernes, 26 de octubre de 2007

PIAB, programación orientada a aspectos, aventuras validando un toco de datos y más...

Siguiendo con mi aventura de la aplicación con muchísimos formularios con muchísimos campos, me encontré con el siguiente problema: necesitaba validar muchas propiedades de muchas clases para luego persistirlas en la base de datos, bien, el tema es que se trataba de una tarea repetitiva además de molesta, como estoy utilizando Validation Application Block me veía ante la nada envidiable tarea de agregar cada clase al App.config considerar todos los campos que necesitan validación (en realidad todos ya que los campos en la base de datos tiene un límite) y colocarle un String Lenght Validator configurado a cada uno, a esto sumarle el mensaje de error; una tortura china podríamos decir. Como a mi, ni a ningún desarrollador que se precie, me gusta realizar tareas repetitivas comencé a darle vueltas al tema para encontrar una solución más piola, y llegó…
Vamos a resumir el escenario, muchas clases con muchas propiedades que es necesario persistir en la base de datos, por lo tanto cuanto menos es necesario validar el largo de los campos.

Tenemos dos opciones

• Un “if” en cada propiedad (no se me ocurre una cosa más fea en una aplicación)
• Utilizar Validation Application Block, pero tenemos el problema de la configuración para cada propiedad.

La solución Enterprise Library desde su versión 3 trae incluido un application block que tenía en la cabeza esperando la oportunidad de utilizarlo, esto me lleva a explicar de qué se trata es el policy injection application block PIAB.

Programación orientada a aspectos

Este extraño nombre es el que lleva un paradigma de programación que se basa (básicamente) en la siguiente idea: toda aplicación contiene aspectos que la atraviesan que se pueden separar modularmente, por ejemplo, una aplicación puede tener un “logeo” de lo que pasa, que va más allá de la lógica de negocios, simplemente se trata de “logear” lo que está ocurriendo, esto es claramente un aspecto, no tiene relación con el objetivo de la aplicación y realmente “ensucia” el código (scattered code ó código dispeso), bien, la POA se basa en que estos aspectos se pueden agregar de otra manera sin ensuciar la lógica básica de la aplicación.

Policy injection application block

Como dije antes Enterprise library tiene un AB para programación orientada a aspectos que lleva el nombre de policy injection application block (PIAB) que nos permite inyectar aspecto, algo interesante es que tenemos aspectos predefinidos, los más suspicaces imaginaran cuáles, los otros application blocks (además de otros), es así que podemos indicar sin necesidad de código que se invoque al validation application block, security application block, logging application block, caching application block y algunas cosas más además de nuestros propios aspecto, vamos a explicar de un modo sucinto cómo funciona.

Primero que nada PIAB se basa en dos conceptos básico:

• Matching Rules: Son las reglas que nos indican qué interceptar para aplicar los aspectos.
• Handlers: Son los encargados de inyectar los aspectos sobre los elementos que cumplan con las matching rules.

Matching rules

Hay muchísimas y muy interesantes, por supuesto podemos crear las nuestras, a continuación enumeramos algunas:

• And matching rule
• Assembly matching rule
• Custom attribute matching rule
• Member name matching rule
• Method signatura matching rule
• Namespace matching rule
• Property matching rule
• Parameter type matching rule
• Return type matching rule
• Tag matching rule

Handlers

Como dije antes tenemos handlers para los application block (logging, validation, catiching, security), y otros más además de poder crear los nuestros, enumeremos algunos:

• Authorization handler
• Caching handler
• Cursor handler
• Custom handler
• Exception handler
• Transaction scope handler
• Validation handler

Para lograr esto necesitamos que nuestra clase herede de MarshalByRefObject e instanciarla a través de PolicyInjection del siguiente modo

Persona p = PolicyInjection.Create<Persona>();

La otra opción es “wrappear” una clase existente de esta forma

Persona p1 = PolicyInjection.Wrap<Persona>(p);

El comportamieno del PIAB depende del handler, por ejemplo si colocamos una matching rule para que intercepte cuando se hace set de una propiedad y la asociamos a un handler del logging, en cuanto en algún sitio de la aplicación se asigne valor a dicha propiedad se van a loger un conjunto de datos, si la asociamos a un validation hadler y no pasa la validación va a lanzar una excepción, etc.

La gran solución

Así es que me di cuenta (en realidad estaba pensado así sólo que yo no lo sabía) que podía crear una property matching rule y agregar todas las propiedades, por ejemplo, que fueran string y tuvieran el mismo largo máximo, agregar un validation handler contra una regla para el tipo string que tenga un range validator que verifique el valor de la propiedad lenght, veámoslo un poco más gráfico.



Código
Persona p = PolicyInjection.Create<Persona>();            

try
{
 p.Apellido = "Ariel Arnaldo Ortega";
}
catch (ArgumentValidationException ex)
{
 foreach (ValidationResult result in ex.ValidationResults)
 {
  Console.WriteLine(result.Message);
 }
}
El PIAB intercepta las clases más precisamente el momento en que se hace “set” de alguna de las propiedades enumeradas, acto seguido llama al handler que invoca al VAB, este tiene una regla para el tipo string (string como las propiedades que quiero validar), sobre su propiedad lenght a la que le aplica un range validator que permite validar que el largo se encuentre en los valores que yo necesito, digamos entre 5 y 10, en caso que la validación no sea exitosa el PIAB lanza una excepción (esta parte es medio fea pero no había otra forma de hacerlo según me parece) y dentro de ella se encuentra el Validation Results con el resultado de la validación, con esto logro resumir en 5 reglas la validación de 300 campos, mágico, hasta la próxima.

1 comentario:

Unknown dijo...

Me parece muy interesante el tema y sobre todo la aplicación que se puede realizar en el. Tendras información en pdf que me pudiera servir de tutorial para aplicar la programación orientada a aspectos.
Aún no he encontrado información que me sirva sobre todo para aplicarla en C#. Agradeceria tu apoyo. Saludos.