Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#

Service locator is not an anti pattern

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
3 Oct 2012LGPL34 min read 26.5K   8   18
I'm getting really tired of all blog posts that states that service locator is an anti pattern. It's not.

(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. 

Another blog:

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:

C#
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: 

C#
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 control 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:

C#
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.

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. 

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Founder 1TCompany AB
Sweden Sweden

Comments and Discussions

 
QuestionArticle updated Pin
jgauffin3-Oct-12 2:48
jgauffin3-Oct-12 2:48 
QuestionShines... or blinds... Pin
Mark Seemann2-Oct-12 9:38
Mark Seemann2-Oct-12 9:38 
AnswerRe: Shines... or blinds... Pin
jgauffin2-Oct-12 20:41
jgauffin2-Oct-12 20:41 
GeneralRe: Shines... or blinds... Pin
Mark Seemann2-Oct-12 21:53
Mark Seemann2-Oct-12 21:53 
GeneralRe: Shines... or blinds... Pin
jgauffin2-Oct-12 21:58
jgauffin2-Oct-12 21:58 
GeneralRe: Shines... or blinds... Pin
Mark Seemann4-Oct-12 6:59
Mark Seemann4-Oct-12 6:59 
GeneralRe: Shines... or blinds... Pin
jgauffin4-Oct-12 7:17
jgauffin4-Oct-12 7:17 
QuestionService Locater an anti pattern Pin
Martin Bohring2-Oct-12 5:59
Martin Bohring2-Oct-12 5:59 
AnswerRe: Service Locater an anti pattern Pin
jgauffin2-Oct-12 6:11
jgauffin2-Oct-12 6:11 
QuestionServiceLocators are not the same as IoC containers Pin
John Brett2-Oct-12 2:12
John Brett2-Oct-12 2:12 
AnswerRe: ServiceLocators are not the same as IoC containers Pin
jgauffin2-Oct-12 2:21
jgauffin2-Oct-12 2:21 
GeneralRe: ServiceLocators are not the same as IoC containers Pin
John Brett3-Oct-12 1:31
John Brett3-Oct-12 1:31 
GeneralRe: ServiceLocators are not the same as IoC containers Pin
jgauffin3-Oct-12 1:39
jgauffin3-Oct-12 1:39 
GeneralRe: ServiceLocators are not the same as IoC containers Pin
jgauffin3-Oct-12 3:52
jgauffin3-Oct-12 3:52 
QuestionSubscribersResolver instead of ServiceLocator Pin
Michał Zalewski2-Oct-12 1:53
Michał Zalewski2-Oct-12 1:53 
AnswerRe: SubscribersResolver instead of ServiceLocator Pin
jgauffin2-Oct-12 1:55
jgauffin2-Oct-12 1:55 
QuestionDoubts Pin
Helluin1-Oct-12 11:03
Helluin1-Oct-12 11:03 
AnswerRe: Doubts Pin
jgauffin1-Oct-12 18:40
jgauffin1-Oct-12 18:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.