Service locator is not an anti pattern.

(this article have been rewritten since it didn’t seem like I managed to communicate my thoughts properly)

There are several blog posts that states that service locator is an anti pattern. With this article I’ll try to explain why it’s not. Do understand that I’m not saying that it should be used for dependency management.

Let’s start by examining where the pattern doesn’t fit (which most blog entries uses as a “proof” for when it’s an anti pattern).

Here are two quotes from different blogs:

In short, the problem with Service Locator is that it hides a class’ dependencies, causing run-time errors instead of compile-time errors, as well as making the code more difficult to maintain because it becomes unclear when you would be introducing a breaking change.

The problem with a Service Locator is that it hides dependencies in your code making them difficult to figure out and potentially leads to errors that only manifest themselves at runtime. If you use a Service Locator your code may compile but hide the fact that the Service Locator has been incorrectly configured. At runtime, when your code makes use of the Service Locator to resolve a dependency that hasn’t been configured, an error will occur. The compiler wasn’t able to help. Moreover, by using a Service Locator you can’t see from the API exactly what dependencies a given class may have.

So what they are saying is that the pattern can hide dependencies and force you to run your application to discover it. I fully agree. It can do that.

Here is the most common example to illustrate that:

public class SomeService
{
	public void DoSomething()
	{
		ServiceLocator.Resolve<ISomeRepository>().Save("kdd");
	}
}

I agree 100%. The service locator do not work very well in that case. I strongly discourage you from abusing the locator in that way. Dependencies/information which is required should always be injected through the constructor. So a better solution would be:

public class SomeService
{
	ISomeRepository _repos;
	
	public SomeService(ISomeRepository repos);
	{
		if (repos == null) throw new ArgumentNullException("repos");
		
		_repos = repos;
	}
	public void DoSomething()
	{
		_repos.Save("kdd");
	}
}

Is it an anti-pattern?

We have identified use cases where the pattern doesn’t fit. Does that make it an anti pattern? Of course not. Let’s examine when it’s perfectly valid.

Let’s start with the very definition of service locator (from wikipedia):

The service locator pattern is a design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong abstraction layer. This pattern uses a central registry known as the “service locator” which on request returns the information necessary to perform a certain task.

What it’s saying is that the service locator basically is something that abstracts away the mapping between the requested type and implementations of something. That is that when requesting a service we do not have to care about the actual implementation.

Doesn’t that sound awfully a lot like a inversion of contol container. It does. Because an IoC container is nothing more than a service locator with lifetime management when all registrations have been configured.

Let’s start by taking an example from the SimpleInjector documentation:

public partial class User : BasePage
{
    private readonly IUserRepository repository;
    private readonly ILogger logger;

    public User()
    {
        // 5. Retrieve instances from the container (resolve)
        this.repository = Global.Container.GetInstance<IUserRepository>();
        this.logger = Global.Container.GetInstance<ILogger>();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        // Use repository and logger here.
   }
}

He do warn about using the container as service locator. But the point is that every container can be used as a service locator. Why is that? Because it’s the easiest way to allow others to take advantage of all services that the container manages.

So when you are using any framework that have IoC support (like ASP.NET MVC) you can safely assume that they use the service location features of your favorite container.

A specific example

Someone suggested that the factory pattern could be used as an alternative. The problem with the factory patterns are that they should always return a new instance of an object each time they are invoked. If you do not do that you do not implement the factory pattern correctly.

ASP.NET MVC has something called action filters which allows you to invoke code at certain points in the execution pipeline. It can for instance be to commit a transaction once an action method have been executed or to authorize the user before an action have been executed.

Let’s assume that we create a factory for the controllers and one for action filters. And per definition they create a new filter or controller upon each invocation. That is not a problem since a new one should be created open each invocation. However, if the action filter should be able to commit the transaction it has to be able to access the same transaction instance that is used in the controller services (like a user repository). That is not possible if our factories just create new instances.

To get around that problem we have to start to manage transactions using solutions like [ThreadStatic] or the HttpContext. Thus introducing more complexity to the application compared to using service location.

However, the factory methods could be able to generate controllers and filters that use the same instance of the transaction. And they could do that by using the service locator in ASP.NET MVC (i.e. DependencyResolver). It’s still service location, but it’s hidden as an implementation detail in the library.

Summary

My point is that you can abuse any pattern, but that doesn’t make it an anti pattern. The reason to why Singleton and Service Locator got such a bad reputation is that they are easy to understand, implement and use. The problem is that the implementors/users haven’t fully understood the problem that the patterns are trying to solve.

Here is a challenge for all of you that claims that it’s an anti pattern:

Pretend that you are developer at Microsoft working with ASP.NET MVC. You want to let your framework users inject dependencies into the Controllers. But since you’ve read that service location is an anti pattern you’ll want to replace it with something else (which supports scoping).

Anyone of you that can present a solution which is cleaner than my defined interfaces above will get my eternal respect.


  • Gurra777

    Good thougts.

  • Mikael Klint

    Very good article.
    Somewhere you have to kickstart the IoC. As a part of the framework, service location is a good pattern when kickstarting the IoC. Though service location should never be used in a domain code.

  • Robert Slaney

    Nice view point. Contrast MVC 1 with MVC 3 / 4. There were many factories in MVC 1 that you could hook into to introduced DI into the stack, like the ControllerFactory.

    Move forward into MVC 3 and the DependencyResolver now replaces most of the static Factory and Provider wrappers, but you have no idea what will be asked for in the GetService call without running the application. At best you be asked for all instances at bootstrap, at worst it will be in dribs and drabs as the application executes.

    The key is a good DI solution to control the aspect of the framework/API that instantiates your objects. Using a locator does not achieve that aim.

    Let’s revisit the MVC4 dependency resolver.
    There are 3 interfaces/abstract classes it will ask for :
    IViewPageActivator, IControllerFactory and ModelMetadataProvider. But you would never know that without running the application. If you using the WebAPI it will also request IHttpControllerActivator.

    I would much prefer an ObjectFactory approach where each “service” is an virtual property and/or method. This way you could easily get the current implementation and then wrap and provide a facade if required. You cannot do this with MVC4 as the default implementation is only created if you don’t supply an instance from GetService, but by then it’s too late in inject your own. Even worse is that the default implementations are usually internal or private classes.

    With WCF you can accomplish DI by providing an IInstanceProvider implementation.

    • http://www.gauffin.org jgauffin

      That’s probably the best comment I’ve got so far regarding my service locator post (here and at CodeProject.com).

      Yeah. The extension points in ASP.NET MVC is a bit cumbersome. They should have had someone which is responsible of designing all extension points so that they’ve got a unified API.

      I think that they created the DependencyResolver just because most users will use the IoC container to provide everything. But it should really have been split up into two different service locators. One for framework integration and one for injecting business classes.

      The problem with the current solution is that it’s not clear what the lifetime is for each service should be. For instance I’ve tried to use DependencyResolver to register the validator and metadata providers for my Griffin.MvcContrib in MVC. That didn’t work very well since they did not get the lifetime that I expected.

      However, if we look at the DependencyResolver from a strict integration point for your average LOB application it’s great. Since in that case the framework can’t really tell what’s getting injected. You also get scoping around the HTTP request (i.e. the IoC container can clean up everything when the child scope is disposed) and it’s easy to create the adapter. Hence I would probably still use it instead of the IHttpControllerActivator.

      But if we look at the extension points for the framework the DependencyResolver isn’t really that great. The abstract factory that you suggested would probably have been a better solution. You forgot the ModelValidatorProvider though. There can be several implementations of it at the sametime. So the existing singleton should probably be left.

      My WCF integration can be found here: https://github.com/jgauffin/Griffin.Container/blob/master/Source/Griffin.Container.Wcf/ServiceLocatorInstanceProvider.cs (another file contains the

  • ben

    After 10 years of using it I’m beginning to think IOC / DI is an Anti Pattern ….so the fact that a service Locator is also one doesn’t surprise me .

    The fact is an IOC container ( and a service locator ) expose a significant amount of code to anyone that has access to it . Mark Miller wrote a very good paper a number of years ago how classes should be regarded as capabilities and should obey POLA .

    Yes you can use constuctor injection but this just limits its badness and introduces worse issues like rarely used but expensive objects. This means you need to be aware how expensive an object is to create and how much its used to determine whether to use DI … which is not a good thing .. And then what do you do ? Call the Container in the methods that use it ? Lazy load it ( Which may be an issue if it uses a lot of memory and is not disposed) . Obviously the best thing is to pass it in from the caller .. but if that is valid why inject from the constructor ? Is it just because we have a proliferation of infra structure objects / factories which dont really belong on methods ( or we like to see on methods .. ) ?

    In addition there is the well established issue of not knowing what code will run and how the app is wired up, so you loose the quick learning curve and parsing of code to get to where you want.

    I think the proliferation of IOC is just because as developers we are too lazy in working out how to structure our apps so classes only have the minimum access needed. This is not much better than global statics. Maybe OO is just wrong and we should use SOA style coupling ..

    .Anyway im lost…

    Anyway if we persist with DI we should use small scopes for the container .

    maybe constructors should look like this Constructor ( subContainer , IMyCommonType)

    {

    }

    Ben

    • JonasGauffin

      I do agree with everything you say. However, I don’t blaim the container but a) the lazy developers b) container implementors that add too many features. A container applies to SRP too.

      I’ve also seen the pattern with users that think it’s OK to create a really big application just because they can do it in a loosely coupled fashion with the help of the container. It is, just as you say, better to create smaller applications using SOA or messaging. However, I would probably still use the container in them.

      As for the lifetime I always try to keep it short. When I use commands each lifetime spans over a command only. In windows services the lifetime is only when a new job is executed. In MVC it’s during the request. In winforms it’s over the command execution again.

      I do love to use an container, but it’s no magic bullet.

      • Scott

        “I don’t blaim the container but a) the lazy developers b) container implementors that add too many features.”
        I completely agree with this statement, especially the first part.
        Truth is, there is way too much hype around service locator being an anti-pattern and dependency injection frameworks (or other forms of dependency inversion) being a silver-bullet. It boils down to the fact that the human species likes to “take sides”, to become far to attached to one thing over another, to create camps of like-minded individuals with little tolerance for questioning the mental status quo (la cage aux folles).
        Software engineer, though creative, is fundamentally a science. It requires objective observation (never mind quantum mechanics for the moment) of functional and non-functional requirements. Then, after significant analysis, one should select the technologies (patterns, frameworks, platforms, etc) based on those requirements and not because “I like this pattern”, or so and so “said this pattern is an anti-pattern” just because, or any other bigoted view not based on actual fact. By fact, I mean that which can be reproduced time and time again yielding the same outcome. Technology is far too contextual! Not to mention it is always evolving.
        Bottom-line: IT individuals who state that any technology is a silver bullet are doomed to a limited existence and limited, even flawed outcomes. Call it laziness, or some other form of “ignore”-ance. It boils down to people becoming far too attached to a technology – as though it were their lover – which is kinda neurotic.
        I always say: “Consider everything in its context, including what I just said.” After all, are we not developing software for the purposes of doing business (directly or indirectly)…therefore…select the technologies that best match the requirements? (Rhetorical and IMHO)

    • http://www.Marisic.Net/ dotnetchris

      Just don’t conflate the Dependency Inversion Principal with IOC Containers. You don’t need a container at all to properly adhere to the DIP.

  • Pingback: An IOC Container using Variadic Template - jSolutions Blog()

  • Pingback: Wie sage ich es meinem (Service)Manager? - Zend Framework Magazin()

  • Cygon

    I can’t follow your argumentation there.
    To me, the second example demonstrates even worse design that the first. It not only is a first class example of what makes service locator an anti-pattern (the User class is going shopping for services and without reading the code/docs, one wouldn’t have a clue which other services it accesses), it also combines it with global variables. A true dependency nightmare.
    Additionally
    – If you want to unit test that, you’d have to push your mocks into this ‘Global.Container’. That prevents multiple tests from running in parallel right there because only one mock can be active at the same time.
    – If you add an additional service dependency to your class, it will only blow up at runtime (or possibly even create a non-mocked instance of the service in unit tests)
    – You need to run binding setup code before your unit tests can run. Thus, in the strictest sense, you aren’t even able to unit test one class in isolation and you’re actually doing integration tests.
    – Your class now depends on one specific IoC implementation. Whereas with constructor-injected dependencies the class could be used without any IoC container.
    All possible uses of a service locator class promote the kind of bad design the two examples in your post show, that’s what makes it an anti-pattern.
    The replacement in ASP.NET MVC is straightforward constructor injection. Any ASP.NET MVC bridge for popular IoC containers offers constructor-injected controller factories. Scoping (singleton, thread, call, session) is easily configured through the bindings, unless you’re referring to something else.

    • http://blog.gauffin.org/ jgauffin

      Ehh. I don’t follow your comment at all? The example shown was to demonstrate where the pattern do not fit.
      ASP.NET MVC uses service location internally to allow devs to use constructor injection and that was my point. Without service location it would be impossible to do that.

  • C. Shea

    Your example of the use of Service Locator as not being an anti-pattern is exactly what Mark Seemann talks about in his book DI in .Net in terms of it being an anti-pattern. You are hiding the fact (from the compiler) that in order to use a User object, you need to have an instance of a IUserRepository and an ILogger. When instantiating a User from a third party component, the third party potentially has no idea that User requires an IUserRepository and an ILogger implementation. If you had used straight up DI and Constructer Injection, the third party would immediately know that User has a dependency on those interfaces and knows they must be provided (either statically or resolved through some container). Also, by using Service Locator, you are now spreading out calls to instantiate dependencies for the system across your system. There is no coherent view of what your system depends on. Also, there’s a chance that when you call the Service Locator to instantiate a dependency, that the locator has not been configured (yet) with that dependency, also causing brittleness. Also, it violates the Register, Resolve, Release pattern. There are no two ways about it. Service Locator is an anti-pattern. Everywhere Service Locator is used could be refactored to use DI instead, resulting in only one place where all dependencies are registered and resolved. If there’s a problem with the container, you know where to look–in the application seam, where your DI container is setup and called to resolve all dependencies needed by the application.

    • http://blog.gauffin.org/ jgauffin

      I love to see how you would solve constructor injection in controllers in a library like ASP.NET without using service location. The constructor patterns (like factory pattern) can’t help as the same instance of a service might be shared between classes. The problem is that the library code have to be able to identify and manage a set of services which are not know at compile time nor the life time of those services.

      An inversion control container used through service location is the least complex solution for that problem. All other solutions will either be more complex for the user or the library developer. I would love to see you prove me wrong.

      We also have to remember that the term ‘Anti-pattern’ was coined as a reaction to the ‘Design Patterns’ book that GOF released. It isn’t a term that are used to label patterns that people doesn’t think apply any more.

      The term ‘Anti-patterns’ is defined to “An anti-pattern (or antipattern) is a common response to a recurring problem that is usually ineffective and risks being highly counterproductive”. I don’t see how Service Location fit that description.

      • C. Shea

        Well, for one, MVC 1.0 provided the IController interface, the ControllerBase base class, and if needed, an IControllerFactory (and probably a base, concrete implementation of that) that you could inherit from and tell MVC to use in place of its default implementations of those. This is how we did dependency injection in Asp.Net MVC 1.0.

        As far as service lifetimes between controllers and controller instantiation: Most dependency injection libraries allow you to control the lifetime of an instance registered with the container. For example, Microsoft’s Unity library has ContainerControlledLifetime (a/k/a single instance shared among all classes), PerHttpRequestLifetime (a new instance is created for each controller request), TransientLifetime (a new instance is created whenever the type is requested from the container–essentially, its lifetime is not controlled, as soon as the object goes out of scope, it can be GC’d), and there’s even a PerResolveLifetime (the first time the object is requested from the container , a given web request–for eample, the type is constructed; subsequent requests for the type during the current request result in the same instance being returned by the container).

        So, as you can see, MVC 1.0 had DI in mind and built-in right out of the box. And, most dependency injection libraries (read, the most common, most used ones) allow you to control object lifetimes.

        Mark Seeman has an example of creating a base controller wired up for dependency injection and subsequently configured to be used as the base controller by Asp.Net MVC in his book I mentioned in my original comment.

        Service Location is an anti-pattern because it hides the dependencies inside the service locator that is passed around to all of your classes. Typically, you’d have:

        Public class MyObject
        {
        . public MyObject(ServiceLocator locator)
        . {
        . ServiceLocator myLocator = locator;
        . IMyDependency dep = locator.Resolve();
        . }
        }

        If someone didn’t know any better (for example, someone consuming a library you developed using service location), they could just ‘new MyObject()’ with any old service locator not containing the required dependencies, and bam!, NullReferenceException–possibly many times, until all objects needed to be doled out by the locator are provided.

        Contrast this with dependency injection: ‘public class MyObject(IMyDependency dependency) {…}’ — I couldn’t possibly instantiate this class without providing the required dependency represented by the constructor parameter. The dependencies are known, they’re apparent, and they can be provided by a dependency injection container–if you choose to use DI. It’s a win-win all around.

        Hope that helps.

        • http://blog.gauffin.org/ jgauffin

          I asked you to present an alternative to using a IoC through service location that won’t increase complexity in for instance ASP.NET MVC. I ask that again as you still have not presented a solution.

          I’m well aware of lifetimes in IoCs. I’ve written a container myself. My point was that creational patterns can’t be used as you then loose control over the life time.

          Are you saying that SL is an anti pattern just because you presented a use case where it do not fit? In that case all patterns are anti patterns.

          Your second example about when the locator is not configured properly. Temporal coupling is not just a problem with locators, it applies to IoC containers, Sockets, Database connections etc. Are you suggesting that they should not be used either?

          Do remember that “Anti-pattern” is not a label to put on patterns. Read the wikipedia article for a definition.

          Looking forward to the next reply. Always interested in others perspectives.

          • C. Shea

            So, I read this blog post a long time ago, and my original comment has little resemblance to what’s here now. After having reread the post, I think I understand what you’re trying to say. But, I wouldn’t promote Service Location for managing application dependencies. In fact, Service Locator tends to be more of a fancy name for an abstract factory. And, abstract factories can be very useful. So if that’s how you’re viewing the use of a service locator–where you don’t care about the particular implementation of a service that’s guaranteed to be available to the application–by all means, use a service locator, er, abstract factory.

          • http://blog.gauffin.org/ jgauffin

            As I said, creational patterns like abstract factory cannot be used. They are expected to return a new instance on every call. If you for instance create your own filters in ASP.NET MVC you expect the same unit of work etc to be returned when using the Dependency Resolver.

            The service locator pattern do not but any semantics on whether a new instance should be returned or not, which makes it a better choice than creational patterns (as defined in the GOF book).

            I fully agree that service locator shouldn’t be used as a common solution in business code, and I really do not think that it is. It’s a great pattern for libraries due to the simple definition and the fact that an inversion of control container can be used to implement it. Simple for the library users and simple for the library developers.

            As a library developer you do not actually now which classes are required. That’s configured by the user. Let’s take ASP.NET MVC as an example again. The controllers might request a interface in the constructor. How would you solve that? You can’t just scan all assemblies in the appdomain since they might contain multiple implementations of that interface. Also you do not know if the user expected that dependency to be transient, scoped or single instance.

            The controllers are just one of the extension points in MVC. There are several. Mark Semanns solution is to define one replacement interface per integration point instead of having a service locator interface. I ask why. What advantage would that give from the library user perspective? It would just complicate things without giving any real value. Today most containers can just implement the DependencyResolver interfaces and be done with it. The MVC users just need to download a nuget package and be done with it.

          • C. Shea

            You’re right about lifetime management and the typical abstract factory.

            I would say using the HttpContext is perfectly acceptable. That’s its purpose. It’s an ambient context and precisely the way it should be used. The alternative is to create your own ambient context and register it with your container using either the PerResolveLifetime or SingletonLifetime (both are equivalent, more or less, when we’re talking about web requests). Then you can take a dependency on the ambient context where you can store things like transaction-type classes.

            As far as assembly scanning and possibly duplicately named interfaces…there’s a solution for that (with Unity anyway, and others, I’m sure). You can use named registrations. You shouldn’t probably have many duplicately named interfaces, so these are an exception to the convention. So scan first. Unity will simply overwrite an existing container registration. (This means you don’t have to write a lot of conditional logic to accomplish scanning–though, one could argue that this behavior is poor and could lead to problems–I only know this because it did lead to problems in an application I was working on). Then, go back and re-register those “exceptional” interfaces using a named registration.

            But wait, how do you get the right registration back from the container now in some cases? Some will still just work with a little additional logic to tell the container which registration to use. Others, not so much. For those, you may want to use method injection or property injection (which are sorely underused–these types of injections aren’t needed often, but they are available and perfectly acceptable when the condition warrants). I’ve used this technique to inject into action filters, for instance (though, this is generally not a good idea–the application I was working on, however, left me little choice at the time

  • Pingback: Design patterns and practices in .NET: the Service Locator anti-pattern | Exercises in .NET with Andras Nemes()