IntelliJIDEA Community Edition

IntelliJIDEA Community Edition

Buenas gente, como dice el titulo, recientemente la empresa Jet Brains esta liberando una versión de su IDE que siempre fue pago (excepto para personas que estén trabajando en proyectos Open Source), ahora para toda la comunidad de usuarios y desarrolladores.

Así que es un buen momento para probar un nuevo IDE, ya que también ahora podemos decir que es Open Source.

Les dejo el link, espero comentarios al respecto:

http://www.jetbrains.com/idea/nextversion/free_java_ide.html

Y una demo que se ve bastante buena:

http://www.jetbrains.com/idea/training/demos/CE/03051979_controller.swf

Ya directamente sobre Drools 5.x las charlas están totalmente dirigidas a los módulos principales (Expert, Fusion, Flow y Guvnor) de esta versión. Por lo tanto el publico debe estar al tanto de que la versión actual esta dividida en distintos módulos y lo que se trata de mostrar son las características principales de los mismos. En estas charlas, como es obvio, se suele empezar por Drools Expert que es el corazón de la plataforma.

*Con respecto al titulo del post: JBoss o el mismo equipo de Drools en esta versión 5.x paso a ver al framework como una plataforma que nos permite integrar la manera en la que expresamos el conocimiento de nuestro negocio dentro de nuestras aplicaciones. Aquí es donde aparece la sigla BLiP (Business Logic integration Platform -> http://www.cafepress.com/jbossorg.387860288). Esta sigla deja de lado el termino Knowledge, el cual toma un rol importantisimo a partir de la versión 5.x. Por esto, el nombre del post BKiP, que aunque suena feo, refleja el 100% de la intensión de la plataforma.

Drools Expert

Es el punto de comienzo si estamos empezando a conocer Drools. Si viéramos como esta compuesto/estructurado el código del proyecto, veríamos que básicamente Expert esta conceptualmente compuesto por los módulos: drools-core, drools-compiler y drools-api. Por lo tanto si nosotros queremos empezar a trabajar con Drools, las siguientes dependencias serian requeridas dentro de nuestro proyecto (obviamente usando Maven):

<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-core</artifactId>
  <version>5.1.0.SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-api</artifactId>
  <version>5.1.0.SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-compiler</artifactId>
  <version>5.1.0.SNAPSHOT</version>
</dependency>

Nuestro siguiente paso, en la creación de aplicaciones, seria definir el modelo de negocio que vamos a utilizar, o que estamos utilizando en nuestra aplicación actual. Este modelo, en el mundo Java se suele expresar en POJOs (Plain Old Java Objects). Este modelo de dominio va a ser nuestro punto de partida para poder expresar nuestras reglas de negocio.

Como podrán imaginar, este tipo de charlas no cubre temas básicos como :

  • Que es una regla de negocio
  • Como se expresan las reglas de negocio
  • Gramática DRL
  • etc

Por lo tanto, la audiencia, debe tener un nivel bastante elevado, sino la charla se puede llegar a hacer inentendible y confundir mas que ayudar.

El segundo paso dentro de la plataforma suele ser Drools Flow; que desde mi punto de vista, la disciplina BPM (Business Process Management) es mucho mas amigable que Complex Event Processing.

Drools Flow

Este modulo esta centrado en la representación del conocimiento como Procesos de Negocio. Permitiéndonos definir, administrar y ejecutar nuestros procesos de negocio de manera integrada con nuestro motor de inferencia. Tanto Drools Flow como Drools Fusion fueron grandes pasos en la version 5.x. Ya que ambos diferencian a Drools de sus competidores propietarios.

Por lo general, en las charlas de Drools Flow se hace mucho énfasis en la inversión de control propuesta a los enfoques clásicos de desarrollo. Donde clasicamente teníamos nuestros procesos de negocio que hacían uso de un motor de reglas para tomar decisiones de manera bastante desacoplada.

interaccionClasicaEntreProcessosYMotorDeInferencia

Interacción clásica

Ahora el concepto se invierte, y deja de lado la visión “Centrada en el proceso y desacoplada” para empezar a jugar con una integración mas fina que nos agranda el abanico de posibilidades a la hora de modelar nuestro conocimiento.

Inversion de Control

Inversión de Control

Hasta aca podemos modelar nuestro conocimiento como:

  • Reglas de negocio: usando la gramática DRL para representar la estructura basica (When/Then) de nuestras reglas de negocio.
  • Procesos de negocio: usando el plugin de Eclipse para modelar nuestros procesos de negocio, los cuales estarán representados en XML.

Utilizando nuestro conocimiento de una manera integrada, sin diferencias en las APIs y sin tener que aprender dos herramientas distintas. Aprovechado las increibles ventajas que nos da esta integración.

Para los que conocen Drools 4.x donde Drools Flow daba los primeros pasos, y era contemplado como la evolución de los agenda-groups, que nos permitían organizar las ejecuciones de nuestras reglas en distintos grupos.

Por ultimo tenemos a Drools Fusion, que agrega otra gran disciplina a este conjunto.

Drools Fusion

La otra gran pata de Drools en la version 5.x es Drools Fusion. Fusion, se encargo de agregarle al motor de inferencia la posibilidad de realizar evaluaciones temporales. Algo que por lo general, no suele ser contemplado por este tipo de productos. La puerta que nos abre esta adición es la posibilidad de inferir sobre flujos de eventos que ocurren durante un segmento de tiempo determinado. Esto no es menor, ya que el campo de Complex Event Processing esta basado en este tipo de análisis e inferencias. En pocas palabras Complex Event Processing, es una disciplina encargada de analizar distintos patrones que ocurren en flujos de eventos, donde un factor importantisimo, es el momento en el cual los eventos ocurren. Como podrán ver en la definición propuesta en wikipedia, Fusion se centra en análisis de patrones y correlación entre eventos. Brindándonos la posibilidad de expresar restricciones temporales en nuestras reglas. Otro punto importante en Fusion, es la posibilidad de enchufar, cualquier stream(flujo) de eventos que se generen por una fuente externa, de forma facil e intuitiva en nuestras reglas.

Este tipo de charlas, por lo general incluyen las funcionalidades básicas, la sintaxis para poder inferir sobre flujos o nubes de eventos y por sobre todo, se habla de los 13 operadores provistos por la versión 5.x. Estos 13 operadores, nos permitirán analizar una amplia gama de posibilidades entre la ocurrencia de nuestros eventos.

Como ya es obvio, todas estas características se incluyen en Drools de manera sencilla y extensible.

Drools Guvnor

Para ir terminando, Guvnor nos ofrece una manera de centralizar todo el conocimiento de nuestra organización en un repositorio central, especialmente preparado para almacenar todo el conocimiento empresarial. Si bien nació como puramente un repositorio, muchas herramientas se le fueron agregando, con el fin de permitir ser una herramienta de creación guiada de conocimiento. Las charlas sobre Guvnor, suelen ser orientadas a usuarios finales, que necesitan tener una forma rápida y sencilla para crear y administrar las reglas de negocio. Estas charlas suelen tratar las nuevas incorporaciones de características que posibilitan administrar todo el ciclo de vida de nuestro conocimiento. Cosas que se han ido agregando son: casos de pruebas para nuestras reglas, tablas de decisión guiadas, y próximamente podremos editar nuestros procesos de negocio por medio de esta herramienta web utilizando la notación BPMN2 que esta volviéndose un estándar de-facto, antes de estar totalmente definida.

Conclusión

Si ya entendemos que queremos hacer con Drools y conocemos los fundamentos con los cuales fue construido, usarlo nos llevara hacia una nueva manera de pensar nuestras aplicaciones. Aprovechando la integración de estas tres ramas: Reglas de Negocio, Procesos de Negocio y Análisis de Eventos Complejos encontraremos nuevas y mejores formas de expresar de manera desacoplada(con respecto al código de infraestructura de nuestras aplicaciones) el conocimiento de nuestro negocio. Resultando en proyectos mas claros, mucho mas mantenibles, donde el conocimiento de negocio puede ser evaluado, cambiado y validado por analistas de negocio.

Sobre estos módulos podría estar escribiendo por un largo rato, pero voy a enfocarme en ejemplos con un estilo mas de tutorial, para que los conceptos puedan irse fijando.

Gente, encontré esta pagina (http://www.java-task.com/) que provee un curso bastante interesante para aprender a programar sobre Java EE.

Estaría buenísimo empezar a promover y crear este tipo de sitios mas enfocados en el mundo JBoss.

Espero que a alguien le sea de utilidad y se esperan feedbacks de si hacen falta adaptaciones para trabajar con JBoss (esperemos que no!).

Estando frente al segundo grupo/nube discutida en el primer post de la serie, se nota que este grupo/nube se caracteriza por tener una experiencia y un background teórico bastante altos. Ya que al haber utilizado Drools 4.x los conceptos básicos ya estan cubiertos. Temas como la sintaxis de escritura de reglas de negocio (DRL), los lenguajes específicos para cada dominio (DSL), las secciones de una regla (RHS y LHS) son ampliamente entendidas y términos como WorkingMemory y RuleBase ya no nos asustan.

Si todo esto esta cubierto y tenemos unas cuantas implementaciones de reglas y soluciones de negocio con el el framework, el salto a la versión 5.x es mas que nada conceptual que a nivel tecnológico. Este cambio encima se ve reducido ya que tranquilamente podemos utilizar Drools Expert como venimos usando Drools 4.x, teniendo en cuenta algunas actualizaciones del lenguaje, APIs y algunos features extras.

Si tomamos como foco Drools 4.x y Drools 5.x Expert, podemos estar horas hablando de cosas interesantes. Aquellas personas que tengan varias implementaciones con Drools 4.x probablemente quieran leer o escuchar charlas sobre los siguientes temas, sin ningún orden en particular:

  • Optimizaciones sobre el algoritmo RETE, que optimizaciones se han agregado últimamente, etc
  • Optimizaciones sobre la escritura de reglas y las distintas alternativas que tenemos para expresar nuestras reglas de negocio.
  • Configuraciones sobre performance
  • Benchmarks
  • etc

Viendo la versión 5.x de Drools Expert podemos ver que el foco que se puso sobre el proyecto y las metas obvias fueron:

  • Ser estable y performante, meta lograda por la versión 4.x, por supuesto la versión 5.x agrega madurez y experiencia demostrada en el continuo crecimiento.
  • Sigue siendo una plataforma pensada y desarrollada por desarrolladores para desarrolladores. La inclusión de Guvnor como herramienta de governance atrae mucho la atención para la autoria y el governance de nuestras reglas de negocio.
  • La facilidad de uso es una clara y gran meta dentro del proyecto. La unificación de la API y la extensibilidad provista por la plataforma demuestran un gran crecimiento sobre la ruta futura del proyecto.

Mas allá de estos puntos que tienen como centro a Drools Expert, el cambio importante en la versión 5.x de Drools es el hecho de expandir el concepto de Regla a Conocimiento (Knowledge). Este cambio que al principio solamente parece solo un cambio de terminología, pero en realidad abre infinitas barreras de crecimiento horizontal de la plataforma.

Para correctamente pasar a usar la versión 5.x de Drools, necesitamos lograr entender la magnitud de esta abstracción realizada mediante el uso el termino conocimiento. Tenemos que subir un nivel y aceptar que la definición de reglas de negocio solo es una dimensión de un amplio espectro de representaciones del conocimiento empresarial.

Drools propone una manera, si se quiere decir, genérica, amplia, integrada y extensible para expresar conocimiento empresarial, en el amplio sentido de la palabra. Por supuesto, toda esta abstracción y flexibilidad se ven expresadas en las APIs. Ahora toda la terminología esta basada en conocimiento (Knowledge). Ahora, por ejemplo, términos como RuleBase van a pasar a verse como KnowledgeBase. Ahora no solo pudiendo contener Reglas, sino que conocimiento en general, representado de distintas maneras.

Formas de representar el conocimiento

Actualmente podemos representar el conocimiento utilizando los siguientes conceptos:

  • Reglas de negocio
  • Procesos de negocio
  • Evaluaciones temporales sobre eventos

Lista que es totalmente extensible para que a medida que se necesiten nuevas maneras de representar el conocimiento se puedan agregar módulos para cubrir estas necesidades.

Muchas veces vamos a escuchar decir, que en esta nueva versión de Drools se le enseño al motor de inferencias a trabajar con procesos de negocios y a entender sobre relaciones temporales. En posteriores versiones seguramente que vamos a escuchar que el motor de inferencias esta capacitado para hacer evaluaciones difusas y vaya a saber que nuevos módulos aparecerán en este próximo año.

En el proximo post voy a tratar de resumir que se ve y de que se habla en las charlas de Drools 5.x, ya no con la vision de pasaje de una version a otra, sino que va a ser el primer paso, un paso global para comenzar una serie de post tecnicos para ir guiando el aprendizaje del conjunto de modulos actuales en la version 5.

Gente, para los que no sepan todavia, hay un canal de JBoss donde publican distintos eventos donde la empresa va participando. Ultimamente han agregado al canal los videos de la JavaOne 09, donde tenian un stand chiquito, pero vistoso y daban mini charlas sobre los distintos proyectos.

Les dejo la URL y luego trateremos de embeber el canal en la pagina del JBug.

http://www.youtube.com/user/JBossVideo

Saludos

Continuando con la temática de mi post anterior y todavía sin haber tenido tiempo de formalizar los datos con una encuesta sobre el tema, voy a abordar lo que a mi manera de ver las cosas divide a los grupos/nubes antes mencionados.

De esta clasificación surge el titulo de este post, por eso #1 – Empezando, va a caracterizar a la primer gran nube mencionada anteriormente. Esta clasificación, esta hecha teniendo como base el hecho de que JBoss y todos sus proyectos, estan hechos por desarrolladores para desarrolladores. (Se puede relacionar esto con el termino Middleware, probablemente este muy relacionado, mucha gente no lo alcanza a ver). Con esto ya dejamos afuera todo aquel que no quiera o sepa desarrollar aplicaciones. Esto no quiere decir que el resultado de lo que implementemos con Drools, no pueda ser usado por estadistas, analistas, gerentes, humanos, etc. Todo lo contrario, estos van a ser nuestros usuarios, pero necesitamos ser desarrolladores y tener una formación de desarrollador para entender por completo el fin, la manera de uso y como esta construido Drools como proyecto.

Mas que nada este post esta orientado a estas personas, que ni siquiera conocían la plataforma Drools, o que si la conocían, solamente la conocían por el nombre. Es importante, para este grupo de personas, recibir algo de orientación inicial, debido a que la documentación oficial, toma como base que estamos muy interiorizados con varios temas que a muchas personas les resulta difícil.

Si te sentís desorientado, no sabes por donde empezar, leyendo la documentación te das cuenta de que no manejas conceptos como por ejemplo: de motor de inferencia, motor de reglas, BPM, Procesos, CEP, etc. Este post esta orientado a ir iterativamente agregando distintas fuentes de información para introducir y relacionar todos estos temas, cuyas bases teóricas son fundamentales para entender como funciona Drools.

Por lo tanto a esta altura, tu gran problema es el Background teórico faltante. Y entender como funciona y como esta hecho internamente un motor de inferencia (el core de Drools como proyecto desde que empezó) se hace fundamental para aclarar el panorama. No hace falta irse al otro extremo de saber como implementar un motor de inferencia (me gustaría llegar a esto en algún post) pero si es necesario entender los conceptos básicos de funcionamiento y por sobre todo entender conceptualmente que representa y que soluciona.

Para esto voy a usar este post, para ir actualizandolo con artículos que explican y abordan temas conceptuales y genéricos, no solamente sobre Drools. Abordando los conceptos de motor de inferencias, sistemas expertos, sistemas de producción, etc, la documentación de Drools Expert empieza a tomar otra forma.

Algunos conceptos importantes

Esta sección va a listar algunas definiciones muy cortas, usadas para empezar a entrar en tema, junto con un listado de lecturas de referencia para ampliar cada tema en particular. Por mi parte voy a ir tratando de extraer las secciones de máximo interés para armar una mini guia conceptual que nos introduzca las herramientas necesarias para empezar con el pie derecho.

Sistemas Expertos (Expert Systems)

Se conoce como un sistema experto, un programa o pieza de software, que intenta imitar las decisiones o acciones tomadas por un experto humano en un dominio(rubro) especifico.

Estos sistemas, hacen uso de motores de inferencia, o motores de razonamiento, para ser mas genéricos, los cuales permiten basándonos en el conocimiento de un dominio, llegar a conclusiones a las que un experto humano llegaría.

Referencias:

http://es.wikipedia.org/wiki/Sistemas_Expertos

Motor de inferencias (Inference Engine)

Básicamente es un programa, o pieza de software, que trata de derivar una respuesta basándose en una base de conocimientos. Donde por base de conocimientos, entendemos que es algo similar a una base de datos, pero especializada para guardar conocimiento, ordenarlo y poder obtenerlo fácilmente. Teniendo como foco principal el hecho de poder llegar a nuevas conclusiones, basadas en el conocimiento almacenado.

Estos motores de inferencia, esta fuertemente relacionados con el ámbito de los sistemas expertos, ya que se considera que un motor de inferencia es el cerebro de un sistema experto.

Referencias:

http://en.wikipedia.org/wiki/Inference_engine

http://es.wikipedia.org/wiki/Inferencia

Sistemas de Producción (Production Systems)

Son sistemas muy relacionados con la inteligencia artificial, construidos con bases en reglas (producción/production) y comportamientos asociados. A grandes rasgos, y con mi visión muy superficial sobre estos temas tan teóricos, relaciono la palabra producción no con el hecho de producir algo, sino al revés con que algo se produce y debemos saber que comportamiento tenemos que tomar en ese momento.

Para ser mas claros, estas producciones/reglas están formadas por dos partes. La primera parte es conocida como sensor, pre condición, guarda o solamente condición y es la encargada de describir un estado particular de nuestro mundo.

Cuando nuestro mundo coincide con algún estado expresado por alguna de las N condiciones que podemos tener, se dice que la producción/regla es activada. Aquí es donde entra en juego la segunda parte de la producción, que es llamada acción. La cual se ejecuta cuando la regla es disparada.

La manera mas simple de ver una producción/regla es la siguiente:

RULE "nombre"
IF/WHEN
         CONDITION
THEN
         ACTION

Cuando la acción es ejecutada, podemos decir que la regla ha sido disparada.

Otro concepto importante aquí, es lo que se conoce como memoria de trabajo (working memory), que es la encargada de tener el estado del mundo y sobre cual se ejecutan las acciones. Estas acciones muchas veces tienen la función de modificar el estado del mundo, pudiendo así causar la activación de otras reglas de manera recursiva.

Como últimos detalles, podemos decir que los sistemas de producción deben incluir dos cosas claves:

  1. Un algoritmo para comparar las condiciones y el estado actual del mundo eficiente. (Voy a dedicarle un post aparte a este tema, ya que aca entran los conceptos de forward y backward chainning junto con el algoritmo RETE, LEAPS,TREAT, etc)
  2. Un algoritmo para priorizar activaciones en caso de que dos o mas condiciones se activen al mismo tiempo.

Referencias:

http://en.wikipedia.org/wiki/Production_system

http://www.cse.unsw.edu.au/~billw/cs9414/notes/kr/rules/rules.html

Conclusión

Si bien las referencias son pobres, la idea es ir agregando y refinando los conceptos sobre este mismo post, a medida que las preguntas surjan.

Espero poder avanzar con cada uno de estos temas en particular, para que el background teórico vaya solidificándose hasta que el uso de la herramienta sea solamente comprender como fue implementada cada parte y cada concepto.

Cualquier comentario/corrección sobre los términos y conceptos discutidos aquí es totalmente bienvenida.

Saludos

Este post es mas que nada para reflejar la propuesta de trabajo publicada en el blog oficial del proyecto JBoss Drools.

http://blog.athico.com/2009/07/drools-job-requested-buenos-aires.html

En el link anterior se encuentran los requisitos minimos y la explicación de que se busca en el trabajo.

A resumidas cuentas, mis empleadores andan buscando un nuevo compañero para trabajar a la par mía en el proyecto JBoss Drools. Esto requiere bastante entrega y dedicación en el sentido de que si o si tiene que gustarte y tenes que querer ser parte de un proyecto Open Source con todo lo que esto conlleva.

Si estas interesado, crees que podes cumplir con los requisitos necesarios y tenes la pasional y el deseo de ser parte de un proyecto Open Source. Manda tu CV a mi casilla personal (salaboy@gmail.com) usando DROOLS JOB como subject.

Saludos.

PD: dudas o comentarios seran bienvenidos aqui en el post.

Continuando con los dos post anteriores (post1 y post2), vamos a analizar el comportamiento de la aplicación cuando la misma se ejecuta. La idea es explicar y aclarar el comportamiento del framework para esta situación en particular y además dejar planteado los comportamientos que por lo general se intentan modelar con estos motores de inferencias.

Primero que nada recordemos el código que armaba la sesión de Drools con la que vamos a interactuar:

KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
 kbuilder.add(ResourceFactory.newInputStreamResource(new App().getClass().getResourceAsStream("/rules/juego.drl")),ResourceType.DRL);

 if (kbuilder.hasErrors()) {
 System.out.println(kbuilder.getErrors());
 return;
 }
 Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
 KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
 kbase.addKnowledgePackages( kpkgs );

 StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
 KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);

 ksession.insert(new Juego("Poker",2));
 ksession.insert(new Jugador("Jugador 1"));
 ksession.insert(new Jugador("Jugador 2"));
 ksession.fireAllRules();

Como podemos ver, una vez que creamos la sesión podemos interactuar con ella mediante el método insert(), que va a insertar nuevos Facts/Hechos a la memoria de trabajo que posee Drools para realizar las inferencias. Una vez ejecutado el método insert(), el objeto ya se encontrara dentro de la memoria de trabajo y automáticamente Drools analizara que deducciones puede realizar sobre el.

Análisis de la ejecución

A continuación vamos a ir viendo como se relaciona la salida que obtenemos por consola con la ejecución del código y las evaluaciones que se realizan las reglas sobre los facts.

Cuando realizamos el primer ksession.insert(new Juego(“Poker”,2)); la siguiente linea aparece por consola:

OBJECT ASSERTED value:Juego =Poker factId: 1

Lo mismo sucede cuando insertamos el primero Jugador:

OBJECT ASSERTED value:Jugador 1 - cartas: [] puntos =0 factId: 3

Ahora cuando vamos a realizar el siguiente insert, es decir cuando llamamos al método insert e insertamos un nuevo Jugador, debido a que hay una regla que esta esperando 2 jugadores para activarse, una Activación es creada. Esto significa que ya hay una regla lista para ejecutarse para un set de Facts determinados.

ACTIVATION CREATED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0](2); $juego=Juego =Poker(1)
OBJECT ASSERTED value:Jugador 2 - cartas: [] puntos =0 factId: 4

Si analizamos la linea que comienza con “ACTIVATION CREATED” veremos que nos indica el nombre de la regla que esta cumpliendo con la condición (y sus restricciones) junto con los datos de los Facts que las satisfacen.

Ahora bien, en nuestra aplicación, no llamamos mas al método insert, ahora es el turno de llamar al famoso y querido método fireAllRules(). Este método, se encargara de ejecutar las Activaciones creadas, que se hayan generado con los inserts anteriores. Por esto, las siguientes lineas se mostraran en la consola cuando el metodo fireAllRules se ejecute:

BEFORE ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0](2); $juego=Juego =Poker(1)
ACTIVATION CREATED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [] puntos =0(5); $juego=Juego =Poker(1)
OBJECT ASSERTED value:Poker Dealer - cartas: [] puntos =0 factId: 5
AFTER ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0, Poker Dealer - cartas: [] puntos =0](2); $juego=Juego =Poker(1)
BEFORE ACTIVATION FIRED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [] puntos =0(5); $juego=Juego =Poker(1)
ACTIVATION CREATED rule:Nueva Ronda activationId:Nueva Ronda [18, 4, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 2 - cartas: [] puntos =0(4)
ACTIVATION CREATED rule:Nueva Ronda activationId:Nueva Ronda [19, 3, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 1 - cartas: [] puntos =0(3)
OBJECT ASSERTED value:Nueva Ronda factId: 6
AFTER ACTIVATION FIRED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [13 de Pica, 13 de Diamante, 7 de Trebol, 8 de Corazon, 6 de Corazon, ] puntos =0(5); $juego=Juego =Poker(1)
BEFORE ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [18, 4, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 2 - cartas: [] puntos =0(4)
AFTER ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [18, 4, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 2 - cartas: [2 de Trebol, 4 de Corazon, ] puntos =0(4)
BEFORE ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [19, 3, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 1 - cartas: [] puntos =0(3)
AFTER ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [19, 3, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 1 - cartas: [9 de Pica, 13 de Trebol, ] puntos =0(3)

Todo esto sucede cuando el método fireAllRules() se ejecuta, pero, que exactamente hace este método? Como vemos en la consola, lo primero que este método va a realizar es la ejecución de la activación que se habia generado cuando estábamos insertando facts en la sesión. La ejecución de estas activaciones van a ser loggeadas en consolas antes y después de ejecutarse. Esto es para que nosotros podamos ver, si la consecuencia de la regla que se ejecuta nos modifica el estado actual de la memoria de trabajo.

Como vemos en el log anterior, en las primeras 4 lineas, sucede exactamente esto que estábamos describiendo.

BEFORE ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0](2); $juego=Juego =Poker(1)
ACTIVATION CREATED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [] puntos =0(5); $juego=Juego =Poker(1)
OBJECT ASSERTED value:Poker Dealer - cartas: [] puntos =0 factId: 5
AFTER ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0, Poker Dealer - cartas: [] puntos =0](2); $juego=Juego =Poker(1)

Entre un BEFORE ACTIVATION FIRED y un AFTER ACTIVATION FIRED, de la misma regla podemos ver si la consecuencia de la misma, cambio el estado de algún hecho/fact, se inserto un nuevo hecho/fact o por alguna otra razón se genero una nueva activación. En este caso en particular vemos que se creo una nueva Activación de de una regla llamada “Iniciar Ronda Poker” al haber sido insertado un objeto de tipo Dealer en la consecuencia de la regla “Comienza una ronda de Poker cuando hay n jugadores“.

Si recordamos la consecuencia de la regla “Comienza una ronda de Poker cuando hay n jugadores“, podemos ver que efectivamente esta regla esta insertando un nuevo hecho de tipo Dealer, con lo cual causa una nueva activación para la regla llamada “Iniciar Ronda Poker“.

 then
    $juego.setMazo(MazoPoker());
    Dealer dealer =new Dealer("Poker Dealer");
    insert(dealer); 

Cuando este hecho/fact de tipo Dealer sea insertado en la memoria de trabajo de Drools, la regla llamada “Iniciar Ronda Poker“, que tiene la siguiente condición, genera una activación:

  $juego: Juego(nombre == "Poker")
  $dealer: Dealer() 

Esto se debe a que ya teniamos un Juego, el que nosotros habiamos insertado y ahora la regla anterior inserto un nuevo Dealer, entonces la consecuencia de la regla tiene que ser ejecutada.

Siguiendo esta misma lógica, pueden analizar el resto de las activaciones que se generan, asi modificar el ejemplo para que se generen nuevas o diferentes activaciones según el estado de la memoria de trabajo de Drools.

Consultas sobre la memoria de trabajo

Para ir terminando con este post, solo resta ver la ejecución de cada uno de los queries que se realiza al finalizar todas las inferencias. Es bueno aclarar también que cuando ya no quedan activaciones que ejecutar, el método fireAllRules devuelve el control a nuestra aplicación para que pueda continuar su ejecución.

Cuando el control retorna a la aplicación luego del método fireAllRules(), podemos consultar como quedaron nuestros hechos en la memoria de trabajo. Para esto podemos definir consultas/queries en nuestros archivos DRL que incluimos a la hora de armar nuestra sesión.

En este caso, se agrego la siguiente consulta:

query "Jugador por nombre" (String qnombre)
  jugador : Jugador( nombre ==  qnombre)
end 

Es bueno notar que la sintaxis para definir consultas es la misma que para expresar restricciones en las condiciones de nuestras reglas.

La salida a consola de la ejecución de esta consulta con diferentes parámetros es la siguiente:

El Dealer tiene las cartas:
OBJECT ASSERTED value:org.drools.base.DroolsQuery@f7a53d93 factId: 20
[Carta -> 13dePica, Carta -> 13deDiamante, Carta -> 7deTrebol, Carta -> 8deCorazon, Carta -> 6deCorazon]

El Jugador 1 tiene las cartas:
OBJECT ASSERTED value:org.drools.base.DroolsQuery@f7a53d93 factId: 21
[Carta -> 9dePica, Carta -> 13deTrebol]

El Jugador 2 tiene las cartas:
OBJECT ASSERTED value:org.drools.base.DroolsQuery@f7a53d93 factId: 22
[Carta -> 2deTrebol, Carta -> 4deCorazon]

Donde el código para ejecutar cada una de estas consultas es el siguiente:

 QueryResults results = ksession.getQueryResults("Jugador por nombre", new Object[]{"Poker Dealer"});
 for ( QueryResultsRow row : results ) {
   Jugador jugador = ( Jugador ) row.get( "jugador" );
   System.out.println( jugador.getCartas() + "\n" );
 }

Donde se puede apreciar que estas consultas se ejecutan obteniendolas por nombre y pasando los parámetros como un array de objetos. Luego para recuperar los resultados obtenemos los objetos mediante el nombre de su variable vinculada, en este caso llamada “jugador“. Vale la aclaración de que debería llamarse $jugador para seguir con las reglas de legibilidad.

Conclusión

Vimos un poco como es el flujo de ejecución de este ejemplo propuesto en particular. Espero que esta explicación, también genere dudas e inquietudes sobre como funciona el framework internamente. La idea principal de estos posts, es dejar precedencia para poder escribir artículos mas profundos sobre temas mas avanzados. Espero sus comentarios, criticas y dudas si es que las hay.

Saludos.

PD: nuevamente les dejo el link del ejemplo, para que no tenga que andar buscandolo por todos lados: www.jbug.com.ar/external/playingWithDrools-ExpertIntroduction.zip

Continuando con el ejemplo propuesto en el post anterior, vamos a analizar las reglas propuestas, junto con el modelo de dominio (objetos) propuestos para el ejemplo.

Hay que tener en cuenta que este modelo, fue creado a modo de ejemplo, y puede no contemplar algunas situaciones. Asi que acepto sugerencias, si el ejemplo no les parece el mas adecuado, o se les ocurre algún otro modelo de dominio con el cual ejemplificar.

Les recomiendo que si no leyeron el post anterior, lo lean, ya que explica la estructura del proyecto propuesto y aclara un poco las APIs básicas que vamos a utilizar cuando definimos conocimiento en forma de reglas de negocio dentro de Drools 5.0.

Modelo de dominio

En este ejemplo, vamos a utilizar un modelo de dominio bastante simple para crear algunas reglas de negocio simples. La idea de este dominio es simular un escenario donde podemos definir distintos juegos de cartas y dependiendo de la cantidad de jugadores que el juego necesite, crear una ronda cuando se pueda empezar con algún juego. En este caso, vamos a ver como se podría escribir algunas reglas para que cuando se cumplan las condiciones, el juego definido comience.

Dominio en el Ejemplo

Dominio en el Ejemplo

Como podemos ver en la imagen, la clase Juego nos permitiría definir el nombre del juego y algunos datos genéricos que el mismo debería almacenar. Por ejemplo, todo juego tiene una relación con un Mazo de cartas y cuantas cartas por mano se deberán repartir a los jugadores de dicho juego.

Asi también estan definidas las clases Carta y Jugador, que mantienen información genérica sobre estas entidades que se utilizaran en todos los juegos.

Como podran apreciar, estas clases son simples POJOS (Plain Old Java Objects), por lo tanto, técnicamente no hay mucho que aclarar. Estas clases representaran las entidades que nuestro dominio necesita poder representar las interacciones de la realidad. En otras palabras, estas clases representan la información que se manejara en un escenario real donde tengamos Juegos de cartas.

Especificando reglas de negocio

Una vez que conocemos nuestro modelo de dominio, ya estamos listos para empezar a escribir reglas que van a actuar sobre el. Para esto, vamos  a crear un archivo de texto plano en el directorio /src/main/resources/rules llamado juego.drl.

Para los que no conocen DRL es la extensión que se suele utilizar para los archivos que van a contener reglas de negocios expresados en el lenguaje que propone Drools. A continuación vemos este archivo que pueden encontrar dentro del directorio antes mencionado.


package com.wordpress.salaboy.playing.with.drools
import com.wordpress.salaboy.playing.with.drools.model.Juego;
import com.wordpress.salaboy.playing.with.drools.model.Jugador;
import com.wordpress.salaboy.playing.with.drools.model.Dealer;
import com.wordpress.salaboy.playing.with.drools.model.MazoPoker;
import com.wordpress.salaboy.playing.with.drools.model.Mazo;
import com.wordpress.salaboy.playing.with.drools.model.Ronda;
import com.wordpress.salaboy.playing.with.drools.model.Carta;
import java.util.ArrayList;

query "Jugador por nombre" (String qnombre)
  jugador : Jugador( nombre ==  qnombre)
end

rule "Comienza una ronda de Poker cuando hay n jugadores"
  when
    $juego: Juego(nombre == "Poker")
    $jugadores: ArrayList( size == 2 ) from collect (Jugador())
  then
    $juego.setMazo(new MazoPoker());
    Dealer dealer = new Dealer("Poker Dealer");
    insert(dealer);
end

rule "Iniciar Ronda Poker"
  when
    $juego: Juego(nombre == "Poker")
    $dealer: Dealer()
  then
    $dealer.addCartas($juego.getMazo().getMano(5));
    insert(new Ronda());
end

rule "Nueva Ronda"
  when
    Ronda()
    $juego: Juego(nombre == "Poker")
    $jugador: Jugador()
    ArrayList(size == 0)  from collect ( Carta() from $jugador.cartas)
    //eval($jugador.getCartas().size() == 0)
   then
     $jugador.addCartas($juego.getMazo().getMano($juego.getCantidadCartasPorMano()));
end

Como podemos ver, en el archivo juego.drl, se definen actualmente 3 reglas y una consulta (query). Cada regla delimitada por las palabras reservadas del lenguaje “rule” y “end“.

Una Regla

Cada una de estas reglas tiene un nombre asociado y dos secciones internas que definen la condición de la regla y la consecuencia que se ejecutara cuando la condición sea cierta. Como podemos apreciar las palabras reservadas “when” y “then” son utilizadas para demarcar estas secciones dentro de cada regla.

Luego de la palabra reservada “when“, expresaremos la condición que debera cumplirse para que esta regla se ejecute. Esta condición se expresa en un lenguaje especial donde las restricciones de la condición se expresan utilizando tipos de objetos y filtrando por propiedades. Este lenguaje es llamado DRL (Drools Rule Language) y es muy sencillo de aprender.

Analicemos juntos una de estas reglas:

rule "Comienza una ronda de Poker cuando hay n jugadores"
  when
    $juego: Juego(nombre == "Poker")
    $jugadores: ArrayList( size == 2 ) from collect (Jugador())
  then
    $juego.setMazo(new MazoPoker());
    Dealer dealer = new Dealer("Poker Dealer");
    insert(dealer);
end

La Condición

Como podemos ver, la condición de esta regla especifica dos restricciones que deben cumplirse para que la consecuencia se ejecute. Analizaremos estas dos restricciones y vamos a aprovechar para hacer algunos comentarios de la sintaxis y la semántica con la que se escriben estas restricciones.

 when
    $juego: Juego(nombre == "Poker")
    $jugadores: ArrayList( size == 2 ) from collect (Jugador())

Es importante notar, que hay dos restricciones expresadas aqui, ambas unidas por un operador AND implícito. La dos restricciones que tenemos en esta condición pueden ser expresadas de la siguiente manera en lenguaje natural:

SI…

  • Hay un Juego que se llama Poker
  • Y hay 2 jugadores

Entonces… Consecuencia

Por lo tanto si estas restricciones se cumplen, la consecuencia de la regla se ejecutara. La primer restricción “Hay un Juego que se llama Poker” es expresada con la siguiente linea en Drools:

Juego(nombre == "Poker")

Donde lo unico que estamos expresando aqui es que en la memoria de trabajo que Drools utiliza, tendra que haber una instancia del objecto Juego, por eso se utiliza el tipo de la clase (con la J mayúscula) y luego se hace una restriccion de valor de propiedad, en este caso, que el valor de la propiedad nombre sea igual a Poker. En Drools cada instancia de objeto que es insertada en la memoria de trabajo es tratada con el nombre de Hecho. Esto hace referencia a que cada objecto que insertemos, va a generar en Drools un hecho cierto del mundo real sobre el cual queremos hacer inferencias y deducciones.

La siguiente restricción un poco mas compleja, sin embargo, lo unico que hace es contar que hayan dos jugadores para comenzar el juego. Basicamente para esto, realiza una búsqueda en la memoria de trabajo sobre todas las instancias del objeto Jugador que hayamos insertado y cuando sean dos evalúa como verdadera.

Esta bueno notar, que como con Drools escribimos código declarativo y no imperativo, no podríamos escribir esta segunda parte de la restricción de la siguiente manera:

 when
    $juego: Juego(nombre == "Poker")
    Jugador()
    Jugador()

Debido a que aquí estaríamos expresando que por cada par de Jugadores se debería empezar un Juego. Esto causaría que si en la memoria de trabajo tuviéramos 2 instancias de objetos Jugador, la consecuencia se ejecutaría dos veces, ya que el par [Jugador 1, Jugador 2] es distinto al par [Jugador 2, Jugador 1].

Como ultima aclaración sobre las restricciones en las condiciones, vale la pena mencionar los bindeos/enlaces a variables que se estan realizando en ambas restricciones con: $juego y $jugadores. Estas variables, luego pueden ser usadas dentro de restricciones siguientes o en la consecuencia de la regla, como veremos a continuación.

La consecuencia

Pasando a la consecuencia, solamente hay que aclarar que podemos expresar cualquier código Java que queramos que se ejecute cuando las restricciones de la condición son satisfechas.

then
    $juego.setMazo(new MazoPoker());
    Dealer dealer = new Dealer("Poker Dealer");
    insert(dealer);

Como podemos ver, hacemos uso de dos facilidades que son agregadas a la condición. La primer facilidad usada aquí es la la variable que relacionamos en la condición ($juego) y luego la función/método insert que nos deja insertar un nuevo hecho dentro de la memoria de trabajo desde la consecuencia de una regla.

Interacción y conclusión

Para ir terminando con el post, ya que se hizo muy extenso, lo falta aclarar como interactuamos con la sesión que habíamos creado en el post anterior. Si descargan el proyecto y revisan la clase App.java, veran que luego de configurar y obtener la session interactuamos con ella llamando los métodos insert y fireAllRules.

StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
 KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);
ksession.insert(new Juego("Poker",2));
 ksession.insert(new Jugador("Jugador 1"));
 ksession.insert(new Jugador("Jugador 2"));
 ksession.fireAllRules();

Espero que a grandes rasgos se entienda el post, y como podemos crear reglas que representen nuestro conocimiento para poder interactuar con el. Aparte de querer compartir los lineamientos básicos para utilizar Drools, la idea del post también es generar dudas, para poder establecer un canal de discusión. Asi que espero sus comentarios, criticas y preguntas si las dudas comienzan a surgir.

Saludos

PD: les dejo de vuelta el link del ejemplo para que puedan descargarlo sin tener que ir al post anterior: www.jbug.com.ar/external/playingWithDrools-ExpertIntroduction.zip

Hace tres dias ya, Mark Proctor lider del proyecto JBoss Drools publico en la famosa pagina The Server Side (http://www.theserverside.com) un articulo sobre el lanzamiento oficial de la versión 5.0 de Drools (http://www.theserverside.com/news/thread.tss?thread_id=54698). En este articulo se mencionan las características de la nueva versión, mas varios links de referencia bastante útiles. Mas alla de la nota en si, es siempre bueno ver la respuesta/feedback de la comunidad en estos sitios donde se suelen hacer este tipo de presentaciones oficiales.

Como era de esperarse, si leen los comentarios, aparecieron varias preguntas, y yo espero que aparezcan mas, sobre el solapamiento de funcionalidades con JBoss jBPM. Yo aproveche para contar mi experiencia, para ayudar a todos aquellos a los que le surgen dudas sobre estos temas, tan comunes.

Tanto yo, como el equipo de Drools, estamos a la espera de feedbacks sobre esta nueva versión para poder continuar la mejora del proyecto para el bien de la comunidad de desarrolladores open source.

Les dejo mi comentario en TSS, y espero sus feedbacks al respecto:

http://www.theserverside.com/news/thread.tss?m=c.reply&thread_id=54698#309325

Estaría bueno poder armar este tipo de discusiones en vivo y compartir experiencias con la comunidad de desarrolladores aquí en Argentina, y en latino america para ver la aceptación de herramientas como Drools que van guiando y cambiando constantemente los paradigmas de desarrollo que conocíamos. Si hay algún entusiasta leyendo, lo invito a contactarse conmigo para organizar charlas o discusiones abiertas sobre estas herramientas tan interesantes.

Saludos!

Actualización:

Agrego un link al blog oficial de los core developers de Drools que vieron mi comentarion en The Server Side y me invitaron a compartirlo tambien en su blog: http://blog.athico.com/2009/05/drools-vs-jbpm-personal-experience.html