Patrón Intérprete

0
7131

Patrón Intérprete

Lo primero, os dejo el enlace a las: fuentes de este tutorial

Introducción

En un proyecto en el que estoy participando en este momento (aunque no estoy de técnico, sino de coacher de scrum) se planteó un problema técnico.
Se necesitaba crear una forma rápida de definir y ejecutar una especie de fórmula fácilmente modificable. Yo en seguida me acordé del patrón intérprete
y de la notación polaca (en lugar de (A + B) * C , pues A B + C *). Este simple cambio de notación en la expresión permite que sea mucho más sencilla la
programación de la ejecución de la operación. Si queréis saber más acerca de todo esto, os dejo un enlace (tirando de éste podéis conocer más acerca del patrón intérprete,
de la notación polaca, de cómo pasar de notación infija (A + B) a notación polaca (sufija o prefija).

Definiendo el lenguaje

Lo primero que haremos será definir el lenguaje de nuestro problema. El ejemplo típico y que mejor se entiende es en el ámbito de operaciones matemáticas:

Símbolo Operación Clase Java
+ Suma SumFunction
Resta SubtractFunction
* Multiplicación MultFunction
/ División DivFunction
Cualquier Representación Númérica Valor numérico NumberFunction
@ Logaritmo base e LogeFunction
Cualquier letra [A-Z] [a-z] Variable VariableFunction

Yo creo que con esto es suficiente.

Definiendo el intérprete

Necesitaremos también una clase que interprete la expresión y construya la secuencia de funciones según el lenguaje definido.
A esta clase la llamaremos (en un alarde de originalidad) InterpreterFunction.

Así mismo, para la correcta implementación del patrón, definiremos un interfaz que han de cumplir todas las clases y le denominaremos ExpressionFunction. Además los clientes
que utilicen nuestro sistema pueden necesitar pasar información de contexto para la ejecución de la función (por ejemplo las variables a sustituir).
Esta información estará dentro la clase ExpressionFunctionContext (por ahora la dejamos en blanco):

Empezando con las funciones:

En el código están todas y con sus tests unitarios, os pongo algunas únicamente:

Para implementar esta clase he necesitado completar la clase ExpressionFunctionContext:

Para que entendáis cómo se usan, qué mejor que poner los tests de cada una de ellas:

Ahora vamos a la clase que hace que esto se empiece a entender. Para poder hacer uso de la notación polaca usaremos una pila (Stack) parecido a como lo hacen las calculadoras HP (por lo menos en mis tiempos de universidad) .
Defino la clase como un servicio. De esta manera la pila de ejecuciones ya estará creada. Además, usaremos un fichero de propiedades para definir la expresión que ejecuta. Os la enseño:

Y ahora una par de clases de tests.
Una para probar que funciona correctamente sin contar con Spring. Usamos un Runner de JUnit llamado Parameterized que permite pasar parámetros al test. Así conseguimos
lanzar 6 tests en uno con diferentes parámetros.

Ahora otro test para comprobar que Spring me lo crea correctamente y me inyecta la expresión:

El fichero del contexto de Spring:

El fichero de propiedades es muy simple:

Bueno, pues nos hemos hecho un mini motor de reglas con 11 ó 12 clases (aunque en este caso son operaciones matemáticas), ahora sólo queda buscarle sentido en tu negocio.

Reconocimientos

Gracias a Iván Zaera que hace ya muchos años me dejó patidifuso cuando me contó lo de la Notación Polaca (los de Teleco no solemos saber de estas cosas
y las aprendemos gracias a los informáticos de verdad).

Dejar respuesta

Please enter your comment!
Please enter your name here