Code smells: Service Locator.

Service Locator es un patrón de diseño que consiste en abstraer la lógica de composición y vinculación de componentes en un objeto. Mediante un Service Locator se pueden inyectar dependencias e invertirlas.  Este patrón se considera un anti-patrón debido a su uso, por si mismo no es malo, tiene implicaciones que debes considerar si decides incluirlo en tus proyectos.

El inyector de dependencias es una dependencia.

Service Locator en la práctica es un inyector de dependencias. Este componente tiene la responsabilidad de obtener las instancias de los componentes y realizar su composición. Si usas este componente en lugar de la instanciación normal todos tus componentes van a depender de un componente único, lo que tiene implicaciones al momento de probar y reemplazar componentes, una de esas es que este uso puede convertirlo en un anti patrón.

En el ejemplo anterior se removieron las instancias por el uso del Service Locator, esto en lugar de ayudar a hacer un código más mantenible, solo consigue agregar más complejidad.

Inyectando el Service Locator.

Al igual que ocurre con las dependencias, el service locator puede ser inyectado como argumento de constructor, argumento de método o propiedad. Obvio, lo ideal seria crear una abstracción del Service Locator en una clase abstracta, interface o super clase que permita reemplazar su comportamiento de ser necesario, por ejemplo, cuando se haga testing.

Los peligros de los inyectores de dependencias.

Los inyectores de dependencias tienen implicaciones, te permiten esconder el como un objeto es compuesto y trasladar esa responsabilidad a otros componentes. Si, la lógica de la creación de los componentes que obtienes mediante un Service Locator corren a cuenta tuya.

Si, existen métodos de automatizar la composición de dependencias leyendo los ensamblados y usando reflexión, esto es peligroso. Si tú no especificas el comportamiento de composición de componentes no sabrás que hace exactamente el inyector. Esto puede llevarte a tener fallos en la ejecución del programa. Si vas a separar la lógica de creación y/o vinculación de componentes y se la vas a entregar a un Service Locator asegúrate de que tú eres el responsable de especificar el como se crearan los servicios.

Siempre que puedas, construye componentes que soporten inyección de dependencias.

Los inyectores de dependencias y los componentes preparados para recibirlas vía inyección deben de trabajar en conjunto. No son lo mismo. La inyección de dependencias es la capacidad de un componente de recibir otros componentes necesarios para su funcionamiento desde el exterior. El componente que recibe dependencias no está interesado en el como fueron creadas, estas pudieron ser creadas mediante instancia normal, reflexión o usando un inyector. En ningún momento es necesario un Service Locator para producir componentes con baja complejidad.

Service Locator es útil en sistemas grandes o complejos.

La decisión de incluir un componente encargado de producir dependencias hace sentido solo en sistemas grandes, donde hay una gran variedad de componentes que usar y no todos están en control del equipo.  Tener un inyector de dependencias permite a varios programadores reutilizar componentes o servicios sin necesidad de entender como son compuestos o componerlos ellos mismos.

En sistemas pequeños un Service Locator es innecesario y contraproducente.

La decisión de incluir este tipo de componentes es una decisión de diseño y/o arquitectura del sistema entero.

Autor imagen: Thomas Jensen

Gustavo Sánchez