Los Mejores Motores de Reglas para Java

Los Mejores Motores de Reglas para Java: Una Comparativa

Introducción

En este artículo, exploraremos algunos de los motores de reglas más populares para Java. En aplicaciones críticas, el proceso de mantener la lógica de negocio dentro del código fuente puede volverse demasiado complicado. Utilizar motores de reglas puede simplificar el desarrollo y mantenimiento al separar la lógica de negocio del código fuente. En el mundo de Java, la mayoría de las bibliotecas de motores de reglas implementan el estándar JSR94, conocido como Java Rule API Engine.

1. Overview

La necesidad de motores de reglas en el desarrollo de software ha crecido, ya que permiten a los desarrolladores gestionar la lógica de negocio de manera más efectiva y menos propensa a errores. A continuación, detallamos algunos de los motores de reglas más utilizados en Java:

2. Drools

Drools es una solución de Sistema de Gestión de Reglas de Negocio (BRMS). Drools puede integrarse con jBPM, una herramienta de Gestión de Procesos de Negocio para estandarizar procesos, actividades de eventos, tareas, etc.

Drools utiliza un lenguaje de reglas que permite a los desarrolladores definir la lógica de negocio de forma clara. Aquí tienes un ejemplo básico de cómo se puede utilizar Drools:

rule "Hello World Rule"
when
    // Define your conditions here
then
    System.out.println("Hello World");
end

Si deseas leer más, una introducción a Drools está disponible aquí, junto con un artículo sobre integración con Spring.

3. OpenL Tablets

OpenL Tablets es un sistema de gestión de reglas de negocio y un motor de reglas de negocio basado en tablas de decisión de Excel. Dado que el formato de las tablas utilizadas por este marco es familiar para los usuarios de negocio, ayuda a establecer un puente entre los usuarios de negocio y los desarrolladores.

A continuación, un ejemplo simple de cómo funciona este marco utilizando un archivo de Excel que contiene tablas de decisión. Primero, importemos sus dependencias, que dependen de org.openl.core y org.openl.rules:

<dependency>
    <groupId>org.openl</groupId>
    <artifactId>org.openl.core</artifactId>
    <version>5.26.5</version>
</dependency>
<dependency>
    <groupId>org.openl.rules</groupId>
    <artifactId>org.openl.rules</artifactId>
    <version>5.26.5</version>
</dependency>

Ahora, veamos un POJO de User:

public class User {
    private String name;
    // getters and setters
}

Y una enumeración que representará el resultado de las reglas aplicadas:

public enum Greeting {
    HELLO,
    GOOD_MORNING,
    GOOD_NIGHT;
}

La clase Case envuelve el objeto User y contiene variables que llevan a los resultados:

public class Case {
    private User user;
    // Variables para inferir resultados
    // getters y setters
}

La interfaz IRule contiene la regla inyectada desde el archivo de Excel:

public interface IRule {
    void helloUser(Case aCase, final Response response);
}

La clase Response maneja el retorno de la regla aplicada:

public class Response {
    private String result;
    private Map<String, String> map = new HashMap<>();
}

La clase principal, que desencadena la ejecución de la regla:

public class Main {
    private IRule instance;

    public static void main(String[] args) {
        Main rules = new Main();
        // configurar usuario y caso aquí
        rules.process(aCase);
    }

    public void process(Case aCase) {
        EngineFactory<IRule> engineFactory = new RulesEngineFactory<IRule>(
          getClass().getClassLoader()
            .getResource("openltablets/HelloUser.xls"), IRule.class);
        instance = engineFactory.newEngineInstance();
        instance.helloUser(aCase, new Response());
    }
}

4. Easy Rules

Easy Rules es un simple motor de reglas de Java que proporciona un marco ligero y basado en POJO para definir la lógica de negocio. Puede crear reglas complejas a partir de las primitivas utilizando el patrón compuesto.

Este marco no utiliza archivos XML ni ningún archivo de Lenguaje Específico de Dominio para separar las reglas de la aplicación. En su lugar, emplea clases y métodos basados en anotaciones para inyectar la lógica de negocio en la aplicación.

Puedes ver un ejemplo de “Hola, mundo” de la siguiente manera. Primero, importa las dependencias necesarias basadas en easy-rules-core:

<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-core</artifactId>
    <version>4.1.0</version>
</dependency>

Luego, crea una clase que define una regla:

&nbsp;@Rule(name = "Hello World rule", description = "Always say hello world")
public class HelloWorldRule {

    @Condition
    public boolean when() {
        return true;
    }

    @Action
    public void then() {
        System.out.println("hello world");
    }
}

Finalmente, crea la clase principal:

public class Launcher {
    public static void main(String... args) {
        // crear hechos
        Facts facts = new Facts();

        // crear reglas
        Rules rules = new Rules();
        rules.register(new HelloWorldRule());

        // crear un motor de reglas y ejecutar reglas en hechos conocidos
        RulesEngine rulesEngine = new DefaultRulesEngine();
        rulesEngine.fire(rules, facts);
    }
}

5. RuleBook

RuleBook es un marco de Java que aprovecha las lambdas de Java 8 y el Patrón de Cadena de Responsabilidad para definir reglas utilizando un simple enfoque de BDD (Desarrollo Guiado por Comportamiento).

Al igual que la mayoría de los motores de reglas, RuleBook utiliza el concepto de “Hechos”, que son datos suministrados a las reglas. RuleBook permite a las reglas modificar el estado de los hechos, que luego pueden ser leídos y modificados por reglas más adelante en la cadena. Para aquellas reglas que leen en datos (Hechos) de un tipo y producen un resultado de un tipo diferente, RuleBook tiene “Decisiones”.

RuleBook se puede integrar con Spring utilizando Java DSL. Aquí proporcionamos un ejemplo sencillo de “Hola, mundo” utilizando RuleBook. Primero, agregamos su dependencia que se basa en rulebook-core:

<dependency>
    <groupId>com.deliveredtechnologies</groupId>
    <artifactId>rulebook-core</artifactId>
    <version>0.12</version>
</dependency>

Ahora, creamos la regla:

public class HelloWorldRule {
    public RuleBook<Object> defineHelloWorldRules() {
        return RuleBookBuilder
          .create()
            .addRule(rule -> rule.withNoSpecifiedFactType()
              .then(f -> System.out.print("Hello ")))
            .addRule(rule -> rule.withNoSpecifiedFactType()
              .then(f -> System.out.println("World")))
            .build();
    }
}

Y finalmente, la clase principal:

public static void main(String[] args) {
    HelloWorldRule ruleBook = new HelloWorldRule();
    ruleBook
      .defineHelloWorldRules()
      .run(new FactMap<>());
}

6. Conclusión

En este artículo, hemos discutido algunas de las bibliotecas más conocidas que proporcionan motores para la abstracción de lógica de negocio. Cada uno de estos motores tiene sus propias características y se adapta a diferentes necesidades y contextos de desarrollo.

Consejos prácticos

  • Selección del motor adecuado: Evalúa tus necesidades específicas de negocio. Por ejemplo, si los usuarios no técnicos también estarán involucrados en la definición de reglas, OpenL Tablets podría ser la mejor opción debido a su enfoque en Excel.
  • Mantenibilidad: Considera la facilidad de mantenimiento a largo plazo. Motores como Easy Rules pueden facilitar la gestión de reglas debido a su simplicidad, aunque opten por una implementación más directa en Java.
  • Integración con tecnologías existentes: Si tu proyecto ya utiliza Spring, elegir un motor que se integre sin problemas con esta tecnología como RuleBook puede ahorrar tiempo y esfuerzo.

Armado con esta información, estarás mejor preparado para tomar decisiones informadas sobre la lógica de negocio en tus aplicaciones Java.