Cuánto daño ha hecho… CommonServiceLocator

Hay ideas que aparecen la mejor de las intenciones, que son útiles, incluso muy útiles, pero que llega un momento en que su intención original se pierde, su objetivo se diluye y su uso se deforma hasta que se convierten en malas ideas. Si hace un tiempo hablaba de IValidable, hoy le toca el turno a CommonServiceLocator.

Para los que sigan mi blog no es ninguna novedad que critique el patrón ServiceLocator, pero ¿qué es CommonServiceLocator?

Según su propia página, CommonServiceLocator es:

(…) a shared interface for service location which application and framework developers can reference. (…) provides an abstraction over IoC containers and service locators.

(…) un interface común para localización de servicios que puede ser usado por desarrolladores de aplicaciones y frameworks. (…) proporciona una abstracción sobre los contenedores IoC y service locators.

Su origen se remonta a un post de Jeremy Miller y su finalidad inicial era ayudar a los desarrolladores de librerías a permitir el uso de distintos contenedores de IoC. Como decía Ayende sobre CommonServiceLocator:

The alternative for that is to each library to create its own abstraction layer. A good example of that is NServiceBus’ IBuilder interface, or ASP.NET MVC’s IControllerFactory. That is just annoying (…)

La alternativa a eso es que cada libreria cree su propia capa de abstracciń. Un buen ejemplo de eso es el interface IBuilder en NServiceBus o IControllerFactory en ASPNET MVC. Eso es, sencillamente, irritante (…)

En realidad, CommonServiceLocator define un interface muy sencillo para el cual existen implementaciones específicas para (casi) cada contenedor de inversión de control existente.

public interface IServiceLocator 
{
    object GetInstance(Type serviceType);
    object GetInstance(Type serviceType, string key);
    IEnumerable<object> GetAllInstances(Type serviceType);

    TService GetInstance<TService>();
    TService GetInstance<TService>(string key);
    IEnumerable<TService> GetAllInstances<TService>();
}

Desde el punto de vista de su uso para el desarrollo de librerías, resulta bastante útil, aunque sinceramente, prefiero el IControllerFactory y el IBuilder que menciona Ayende antes que tener un ServiceLocator genérico. Siempre he pensado que es mejor hacer explícitas las responsabilidades. Aun así, me parece buena idea que un framework permita ser usado con distintos contenedores IoC para que los usuarios del framework no acaben necesitando dos contenedores distintos en su aplicación (el del framework y el suyo propio).

El problema con CommonServiceLocator es que llevó a bastante gente a pensar que era la forma “correcta” de usar un contenedor IoC en las aplicaciones. Mucha gente sabía que no debía referenciar IKernel/IWindsorContainer (por poner un ejemplo de Castle Windsor) en sus clases, porque eso implicaba atarse al contenedor, pero pensaba que con CommonServiceLocator esa atadura desaparecía.

El error de este planteamiento es que ataca el problema equivocado. Lo peor de referenciar el contenedor no es depender a una implementación concreta del mismo, sino que las dependencias de la clase dejan de ser explícitas.

El interface CommonServiceLocator favoreció en muchos casos el uso de los contenedores de IoC como meros ServiceLocators, y como ya he dicho otras veces son cosas casi opuestas. Está claro que en este caso la culpa no la tiene el pobre CommonSeviceLocator, sino el (ab)uso que se ha hecho de él y la cegera de algunos desarrolladores.

Un comentario en “Cuánto daño ha hecho… CommonServiceLocator

  1. pregunton dijo:

    Sigue haciendo daño…mucho daño, :'( y más con programadores torpones y ciegos como yo.

Comentarios cerrados.