30.11.05

Drools I. Introducción a los motores de reglas de negocios.

Saludos.

Drools (http://drools.org) es una implementación libre de un motor de reglas de negocio compatible con la especificación JSR-94 Rules Engine API (http://www.jcp.org/en/jsr/detail?id=94). ¿Y qué es un motor de reglas de negocio?. Es un componente que, a partir de una información inicial y un conjunto de
reglas, detectas qué reglas deben aplicarse en un instante determinado y cuáles son los resultados de esas reglas.

Uno de los puntos fuertes de los motores de reglas de negocios es que hablan el mismo lenguaje que el dominio del problema. Un ejemplo típico: supongamos que estamos hablando con un cliente para el desarrollo de una tienda virtual.
Algunas de las cosas que nuestro cliente nos pediría pudieran ser:

Si la cuantía del pedido supera cierta cantidad o si es un cliente de confianza, entonces se le aplica un descuento. Si se compra más de N productos del mismo tipo se le aplica un descuento. Entre las fechas X e Y, un producto está en oferta y, si se lleva 2, se le añade un 3º gratis

En una aplicación normal, todo lo anterior deberíamos codificarlo en métodos de clases que se ejecutaran al procesar un pedido, lo cual no siempre es sencillo. Con un motor, solo tenemos que indicarle las reglas de negocio, e ir indicándole los hechos. En este ejemplo, tendríamos que suministrarle al motor la información sobre los pedidos, clientes y productos mediante clases JavaBean.

Otra ventaja es a la hora de realizar cambios o mantenimiento. Si nuestro cliente desea cambiar el descuento por pedido, o el descuento por número de productos, o las fechas o tipos de productos (o quitar todos los descuentos), con un motor de reglas de negocio sólo es necesario cambiar las reglas, sin necesidad de modificar código, recompilar, ni siquiera de parar la aplicación.

Básicamente un motor de reglas de negocio está compuesto de tres elementos: un conjunto de reglas, el espacio de trabajo (o el conocimiento que tiene), y el procesador de reglas. Las reglas son sentencias de la forma IF-THEN, de tal manera que si se cumplen todas las condiciones del IF se ejecutan todas las acciones del THEN. El espacio de trabajo es donde se guarda el conocimiento (objetos Java) que el motro utilizará para decidir que reglas deben activarse.

Dentro de las reglas pueden existir conflictos. Un conflicto es cuando varias reglas distintas pueden activarse para el mismo conjunto de hechos y, la aplicación de dichas reglas, pueden tener resultados contradictorios. Algunas de las estrategias para resolver conflictos son: asignarle una prioridad a cada regla, estrategias FIFO o LIFO, aplicarlas en el orden en que se declararon o aplicarlas en orden aleatorio.

Existen otros motores de reglas de negocio para java, por ejemplo JESS (http://herzberg.ca.sandia.gov/jess/), Mandarax (http://mandarax.sourceforge.net/) o OpenRules (http://java-source.net/open-source/rule-engines/openrules). También hay
motores de reglas de negocio para plataforma .NET como Quick Rules, JRules o Blaze.

Los motores de reglas de negocio pueden utilizarse, por ejemplo, para desarrollar prototipos rápidos o, incluso, para implementar la lógica de la aplicación. También pueden utilizarse como parte de un sistema de workflow.

En el próximo mensaje pondré un ejemplo de como implementar el caso práctico que hemos visto.

16.11.05

Extendiendo JUnit para que verifique expresiones regulares

Saludos.

A veces, escribiendo pruebas unitarias con JUnit, hemos de comprobar resultados complejos.
Utilizando el soporte para expresiones regulares de J2SE a partir de la versión 4 que comentamos en el mensaje anterior, vamos a escribir un nuevo método assert, por ejemplo assertRegExp, que nos permita validar una cadena respecto de una expresión regular. Una posible implementación de este método se muestra a continuación.


public static void assertRegExp(String message, String regexp, String s) {
if (message==null)
message="";
if (!Pattern.matches(regexp, s))
fail(message+" ["+regexp+"] over ["+s+"]");
}

public static void assertRegExp(String regexp, String s) {
assertRegExp(null, regexp, s);
}


Para que funcione, ambos métodos deben estar en una clase que herede de Assert, TestCase o TestDecorator.

Veamos un ejemplo. Supongamos un método "String getDNI()" para el que queremos escribir una prueba que verifique que el resultado está compuesto de 8 dígitos y una letra mayúscula. Una posible prueba utilizando nuestro método assertRegExp se muestra a continuación.


String dni = persona.getDNI();
String expReg = "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][A-Z]";
assertRegExp("DNI incorrecto", expReg, dni);