El patrón Strategy y funciones anónimas

Publicado en Snippets · 15 abril 2015.

Llevo semanas sin poder escribir debido a la acumulación de trabajo. Esto ha hecho que también se me acumule los posts que tenía pendiente de escribir. Al final, de entre todos los temas, me he decido empezar la serie de patrones de diseño y además por el patrón Strategy. Ya tocaba algo de backend.

¿ Por qué empezar una serie de patrones de diseño cuando hay ciento, o quizás miles, sitios en internet que ya lo hacen ?. Bien, yo tengo una forma peculiar de programar o de diseñar software. Me gusta conocer las buenas costumbres pero luego no las aplico rígidamente, más bien, desarrollo o diseño usando estructuras que siguen el mismo propósito pero no el mismo diseño o implementación que lo recomendado. Lo más puristas lo consideran sacrilegio. En mi opinión, puedo aportar un enfoque diferente que sirva de ayuda en determinadas situaciones.

Para esta entrada consideraré que ya sabes que es un patrón de diseño y sabes sobre el patrón estrategia o Strategy.

Primero, vamos a definir el problema a resolver: Un cliente nos pide hacer una clase que se encargue de visualizar distintas etiquetas HTML, porque no le gusta ningún sistema de plantillas. También quiere que sea compatible con bootstrap o cualquier otro toolkit en el futuro. El cliente también dice que si lo hacemos bien, nos traerá más proyectos( y por supuesto esto último quiere que lo tengamos en cuenta para el presupuesto ). Sí, es un pequeño marrón, pero al menos trataremos de hacer bien las cosas. Vamos a ver distintas soluciones y nos quedaremos con la mejor( spoiler: tiene que ver con el patrón Strategy ):

1.) Podríamos usar una jerarquía de etiquetas usando herencia. Luego, mediante un Abstract Factory instanciarlas. ¿ Pero que pasa cuando salgan nuevas versiones de html con nuevas etiquetas ?. De hecho, ya de por sí sería un un problema si el requisito de nuestra aplicación dijera que debemos ser compatibles con html4.1 y en un futuro cercano html5. Si a sabiendas de esto terminamos usando Abstract Factory, conllevará incumplir el principio de diseño abierto/cerrado. Esto significa que estamos creándonos ya un problema que sabremos que tendremos que solucionar en el futuro.

2.) Podríamos usar Strategy, ya que de etiqueta a etiqueta sólo cambia la parte de visualización( o mejor dicho de algoritmo de visualización). En mi opinión, esta es la solución más idónea y que encaja perfectamente con lo que queremos( en verdad, este caso no es un buen ejemplo de Strategy pero cualquier otro más válido se hacía complejo para exponerlo en el blog ) .

Para hacer nuestra estrategia necesitaremos:

  • Etiqueta: clase que nos servirá de base para crear cualquiera de las etiquetas que necesitemos. Correspondería con el agente Contexto dentro del patrón Strategy.
  • Input, Select, Label, Option, ..., serán las distintas formas de visualizar una etiqueta. Corresponderían con los EstrategiaConcreta dentro del patrón Strategy.
  • Faltaría una interfaz que sirva de contrato de las distintas EstrategiaConcreta. No soy partidiario de usar interfaces en PHP, reducen la eficiencia y no aportan casi nada( en Java son necesarias, en PHP no ). Así que no la añadiré.

Ahora el código, aunque también está disponible de manera más extensa en el bitbucket de trasweb. Este es el script que lanzaremos para probar nuestro código. Como vemos, las etiquetas se crean instanciando desde la clase Etiqueta especificándole mediante un string el tipo('input', 'select') de etiqueta que queremos. Posteriormente, al objeto resultante vamos asignándole los distintos atributos de la etiqueta y finalmente, la mostramos usando el método mostrar()

Veamos ahora la clase Etiqueta En el constructor creamos nuestra etiqueta(estrategiaconcreta). Este también debería de haber sido un Factory Method que nos permitiera instanciar etiquetas de colecciones diferentes. Sin embargo, he hecho una pequeña modificación para que por cada etiqueta podamos escoger una colección diferente. Por defecto, la colección de etiquetas es 'html5' pero es modificable mediante la constante DEFAULT_TAGS que para aumentar su eficacia se podría trasladar de su ubicación actual a un archivo de configuración.

Los métodos mágicos __set y __get nos permiten recoger y utilizar los distintos atributos de las etiquetas.

El método mostrar es el que usa el algoritmo propio de la etiqueta escogida(estrategiaconcreta) para visualizarla. bindTo nos permite lanzar el algoritmo de visualizar como si fuera otro método más de la misma clase Etiqueta. En un ejemplo más correcto de Strategy podría ser que este método hiciera un cambio de disposición del html mediante Javascript en vez de visualizar las etiquetas.

Veamos ahora alguna de las etiquetas, por ejemplo, Option y Select:

Como vemos, cada estrategia concreta es una clase con sólo un método 'mostrar()' que devuelve una función anónima. En esta función anónima, gracias al uso de bindTo hemos ganado facilidad de uso con respecto al Strategy tradicional por contar con un contexto. No siempre es deseable el contexto, aquí nos está sirviendo de utilidad para definir nuevas etiquetas dentro de otras etiquetas o para acceder a los atributos. También podríamos querer el contexto, por ejemplo, para crear un sistema de hook encapsulado de manera que podamos insertar ciertas etiquetas automáticamente bajo ciertas condiciones.

Yo creo que al final hemos hecho un sistema de etiquetado muy molón a la par de simple. Seguramente nuestro cliente estará contento de habernos dejado este trabajo de programación PHP y quizás nos traiga más proyectos en el futuro(o eso dice).

¡ Compártelo !
Este sitio utiliza cookies propias y de terceros para mejorar tu experiencia con el sitio web. Al continuar con la navegación consideramos que acepta su uso.