Introducción
Cuando descubrí MVC en la plataforma ASP.NET, descubrí los patrones, fue cuando conocí a Martin Fowler. Quien a pulso y con mucho trabajo en pro de las metodologías, la arquitectura de software y los patrones, se ha convertido es su represéntate mundialmente reconocido; todo lo que dice sobre estos temas casi es ley. Al menos eso parece, ya que en todos los sitios donde he investigado, usan referencias a su sitio, lo citan como refuerzo de lo que dicen, incluso Microsoft.
En lo personal he leído casi todo lo que he encontrado que lleve su firma y en todo lo que he leído hay mucho conocimiento, las palabras por si solas tiene la autoridad de convencerte. Sin embargo cual fue mi sorpresa que al tratarse de el patrón de Service Locaton, encontré a otro autor que según él, “no solo por que lo diga Martin Fowler en su artículo ya es cierto”, este autor se llama Mark Seemann, y él a su vez en un articulo (que como pude ver tiene como objetivo secundario promover su libro), dice que el Service Locator es un anti-patrón. Hay mucha discusión al respecto en la misma página, donde el autor se da el tiempo para responder a los que se atrevieron a querer discutir el tema.
Nuestro ejemplo
En fin, si les interesa leer en detalle lo que dicen ambos pueden seguir los link que les proporcione a cada artículo, en las líneas superiores, pero si lo que les interesa es ver un ejemplo de la vida real el cual está basado en una serie de ejemplos publicados por Stefano Riccardi en su blog personal, entonces quédense conmigo y veamos lo siguiente.Que es Service Locator?
La forma más sencilla de imaginarnos que es o para que sirve, es pensar en él como un almacén de componentes. El beneficio de usarlo es el alto grado de independencia entre los clientes y el servicio. Puesto que nuestro Service Locator se encarga y encapsula la lógica de creación de instancias (como en el Factory), su inicialización, etc. Los cambios que se deban realizar a estos servicios individuales, no afectan el código de los clientes.
Otro punto de controversia consiste en compararlo con el patrón Singleton, el singleton simplemente es una forma de implementar el Service Locator.
El éxito radica en ofrecer un medio centralizado de administrar servicios de diferente tipo desde un solo lugar, al mismo tiempo que podemos controlar que servicios están disponibles, ya que al implementar la misma interface, podemos añadir nuevos servicios sin que sea necesario hacer modificaciones en los clientes, y del lado de los clientes hacer uso de estos nuevos servicios solo requiere que los soliciten, se usan de igual manera que los que ya usaban.
Mano a la obra:
Ya estuvo bueno de rollo, vamos a lo que nos interesa, un ejemplo.Requerimientos:
En un proyecto en el que estoy trabajando actualmente, el cual partió de ser un Framework para la empresa, se requieren algunos servicios, como son Preguntas Frecuentes, El clima en las ciudades donde tiene oficinas, etc.Solución
Dentro del Framework hay un componente independiente para cada uno de estos servicios, sin embargo en la práctica usar cada uno de ellos, requeriría que tuviéramos que estar creando las instancias, inicializar sus parámetros, etc. Además si dos aplicaciones que estén en ejecución al mismo tiempo requirieran de estos servicios, entonces tendríamos en memoria dos instancias del mismo, lo que afecta nuestros recursos. La solución es usar el Service Locator en la implementación usando Singleton.
Pasó a paso:
Crear servicios
Lo primero seria tener los servicios, llámalos Faq y Weather (se oye mejor en ingles…no es que sea malinchista ), ambos servicios deben implementar la misma interface IService<T>, para que puedan ser manejados adecuadamente:Esta interface, solo les requiere un método, GetData, mismo que servirá para entregar el resultado de sus servicios a cualquier cliente que lo solicite.
Como habrán notado la interface es genérica, lo que quiere decir que al momento de implementarle nos solicitara que le proporcionemos la Entidad que se empleara en sus métodos. (Esta es una de las variantes que lleve a cabo del ejemplo de Stefano).
La implementación del servicio quedaría así: A pesar que en otros post he publicado la forma de implementar un repositorio en esta ocasión voy a incluir el ejemplo, para presentarles el uso de de una biblioteca llamada NBuilder que se emplea para crear datos de prueba.
Es muy simple de usar y muy flexible, la pueden obtener aquí, para usarla deben incluir una referencia al proyecto y un using en el código:
using FizzWare.NBuilder; Nuestro código del repositorio queda así:
Este código generara 5 objetos usando la biblioteca NBuilder, con información del tipo correspondiente de la entidad Faq, cuyo código es:
Service Locator
Este patrón no es muy difícil de implementar pueden encontrar en internet, muchas formas. La mía se basa en la que presento Stefano, aun que según lo que decía Mark Seemann no la implemente completamente independiente.
Como siempre el primer paso es crear una interface: Según el patrón debemos cumplir con los siguientes requerimientos, para que sea exitosa y correcta la implementación:
- Debe ser Singleton, ya que por su naturaleza no es necesario ni recomendable tener dos instancias de ella al mismo tiempo.
- Debe usar Lazy Initialization, para que solo se creen las instancias cuando algún cliente lo solicite.
Veamos el código
Lo primero es Crear la clase implementando nuestra interface:Internamente la clase requiere dos colecciones de tipo Diccionario, la primera para almacenar los tipos de servicio que se pueden instanciar y la segunda para almacenar los servicios que ya fueron instanciados previamente por otro cliente.
Para implementar el patrón Singleton, necesitamos dos variables mas, la primera es una interface del servicio en sí y la segunda un objeto que se empleara para el proceso de hilos seguros:
El constructor de nuestra clase debe instanciar los diccionarios y registrar los servicios que pueden ser solicitados: El método que se encarga de registrar los servicios, simplemente agrega al diccionario de tipos de servicio los tipos de los servicios (valga la redundancia) que se pueden solicitar:
Para implementar el patrón Singleton, agregaremos una propiedad de solo lectura, la cual verifica si la instancia interna del servicio ya fue creada, de lo contrario la crea y después la envía a quien lo solicite; fíjense el manejo de hilos seguro usando lock:
(disculpen que haya cambiado el estándar que siempre he usado con los if, pero lo hice por cuestión del tamaño de la imagen)
El método principal del patrón lo podemos dividir en dos partes, la primera se encarga de verificar si existe una instancia ya cargada del servicio solicitado y si es así, entonces nos la regresa.
La segunda parte se ejecuta si no ha sido cargado el servicio, es aquí donde se lleva a cabo la carga del servicio usando Reflection, para que esto pueda funcionar es muy importante que nuestro servicio tenga un constructor default sin parámetros.
Y por ultimo si ocurre algún error, al tratar de crear la instancia, se infiere que se debería a que dicha llave no exista: En el tester de consola podemos ver:
Espero que sea útil y que se reconozca el crédito de todos aquellos que aportaron información para que se pudiera crear esta implementación.
El poder del código solo es completo, si tenemos el conocimiento de como usarlo.
No hay comentarios:
Publicar un comentario