Implementando nuestro propio motor de reglas — Java.

Antonio Sánchez González
4 min readOct 25, 2017

--

Un motor de reglas es una estrategia en programación para ejecutar acciones acorde a unas condiciones, esto podría sonar como si fuese un simple condicional if-then y en realidad la idea es la misma pero con el motor de reglas tendremos un software mucho más escalable y legible.

Supongamos que tenemos este ejemplo:

Como vemos tenemos una clase llamada FizzBuzz que implementa un método llamado generate, este método nos retorna en base a un número una cadena o el mismo número como una string; Todo depende si el dicho número cumple con las reglas establecidas para FizzBuzz que son:

  • Retorna FizzBuzz si el número es divisible entre 3 y a su vez divisible por 5.
  • Retorna Buzz si el número es divisible por 5.
  • Retorna Fizz si el número es divisible por 3.
  • Retorna el mismo número si no se cumple las condiciones anteriores.

¿Parece una buena solución verdad?, bueno para este caso sí pero ¿y si en vez de tener 3 reglas tenemos 50? el código se nos quedaría con muchos condicionales unos debajo de otros. Esto sería una pesadilla de mantener, generaría una clase muy grande, los comportamientos de cada regla estarían todos en el mismo lugar, se nos complicaría el trabajo a la hora de añadir nuevas reglas. En definitiva es una mala práctica de programación.

Un motor de reglas nos solucionaría todos los problemas anteriormente dichos, pero, ¿Cómo implementamos nuestro propio motor de reglas?. En un artículo llamado Should I use a Rules Engine? de Martin Fowler nos explica como hacerlo.

You can build a simple rules engine yourself. All you need is to create a bunch of objects with conditions and actions, store them in a collection, and run through them to evaluate the conditions and execute the actions.

¿Parece sencillo verdad?, bueno vamos a ello.

Lo primero que haremos es crear una interfaz para definir los métodos que tendrán en común todas nuestras en reglas.

El método condition almacenará la condición de la regla y el método action la acción de la regla.

Ahora crearemos 3 clases (porque nosotros tenemos 3 reglas, en caso de tener más crearemos tantas clases como reglas existan) que implementen esta interfaz, cada clase tendrá su propia condición y su propia acción.

¡Ya tenemos nuestras reglas implementadas!, solo faltaría crear el motor de reglas que será el encargado de almacenar las reglas en una lista y ejecutarlas todas cuando se le diga. Nuestro motor de reglas quedaría de esta forma:

En la clase RulesEngine tenemos un Array que almacena objetos del tipo de nuestra interfaz, como todas nuestras reglas la implementan no tendremos problemas en añadirlas a la lista mediante el método addRule. El método executeRules recibe por parámetro un número que es necesario para pasarlo a nuestras reglas, luego recorre el array y va evaluando cada condición de cada regla; Si se da el caso de cumplirse una de estas condiciones retorna la acción de la regla, en el caso de no cumplirse ninguna retorna el mismo número convertido a String.

Ya solo nos queda refactorizar nuestra clase FizzBuzz para que utilice nuestro motor de reglas.

¡Bonito verdad!.

Podríamos mejorar nuestro motor de reglas añadiendo una variable que establezca la prioridad de la regla y reordenando el vector en base a esta variable siempre que se añade una nueva. De esta forma daría igual el orden en que añadamos las reglas, se ejecutarán por orden de prioridad. Esto ya os lo dejo a vosotros :D.

Un saludo.

--

--

Antonio Sánchez González

Interesado de las nuevas tecnologías y la seguridad informática. Poco a poco este mundo me ha enseñado que lo que realmente me apasiona es desarrollar software.