The Service Locator has been getting a bad press for being an Anti-Pattern. I have used this pattern in the last version on my core code but I won't be using it in the next ...

So what is the purpose of a Service Locator?

To be able to get services for a component which does not tie it to a particular implementation of those services.

Yes I want that, but here are two strong arguments against using this pattern.

Argument 1 - The Singleton Pattern

The first actually boils down to the Singleton Pattern used to implement a globally available Service Locator. Growling at the Singleton Pattern is well known and agreed, basically;

  • Global single state, insists all components use the singleton in a common state - this is tight coupling. For example, for tests to have reliable results, they should be able to run independently, with no external state which may be effected by other tests and give different results depending on which order they are run in.
  • Single Responsibility violation, having responsibility for its own creation and the business logic gives a possible reason for change cascade. You should be able to change a component without changing others.
  • Parallelism, a single mutable object will require a serial access strategy - which means its not parallel.

So, the Singleton is bad, but does the Service Locator Pattern actually include a singleton as part of its implementation? Perhaps it should be thought of as separate to it. Martin Fowler's paper does say ...

"A way to think of this is that service locator is a registry not a singleton. A singleton provides a simple way of implementing a registry, but that implementation decision is easily changed."

Of course, you don't use your Service Locator as a Singleton, you pass it around. That leads on to the next argument.

Argument 2 - Hidden Dependencies

A Service Locator will hide the dependencies of a component from the client.

If a component is able to "locate/resolve" services for itself, anything calling that component will be unaware of the services that are required for it to work.

Problems manifests themselves as a run-time errors when a particular required service has not been registered with the Service Locator, which makes it difficult to code against. The programmer will have to trawl deeper into the code to find its dependencies or use a trial-and-error approach - boo.

Dependency Injection Instead

Specifically Constructor Dependency Injection.

This offers a solution to the above issues, by declaring the dependencies of a component in its constructor;

  1. You ensure that the services required are available when it is instantiated.
  2. They are obvious to anyone programming against it.

Using an abstraction for the service gives you the loose coupling.

class MyComponent {
    MyComponent(IMyService service) { }
}

Here is a nice and testable component, using a Fake or a Mock you can easily test this and swap out different implementations of IMyService should requirements change.

References

http://martinfowler.com/articles/injection.html

http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

Tags patterns
comments powered by Disqus

On Twitter Follow MrAntix on Twitter

DkaliRam 25 minutes ago
DkaliRam

jQuery Based Ajax http://t.co/UAb91pYcpn MVC Google Map http://t.co/piYl8k44IA

a5hpat 26 minutes ago
a5hpat

Getting Started with Web Form and WebAPI using Entity Framework 5 http://t.co/Jr5k93NZqC #ef5

Windows_agent 30 minutes ago
Windows_agent

Step-By-Step: Creating a Windows 2012 R2 Lab in Azure http://t.co/p0XBegtfRZ #windows

UberMCSE 30 minutes ago
UberMCSE

RT @MSLearning: Learn about Windows @Azure as a Service in this FREE on-demand training! Get started: http://t.co/xdGar8LZhn http://t.co/wQpic.twitter.com/wQlipeMHBB

sidney_andrews 34 minutes ago
sidney_andrews

RT @MSLearning: Learn about Windows @Azure as a Service in this FREE on-demand training! Get started: http://t.co/xdGar8LZhn http://t.co/wQpic.twitter.com/wQlipeMHBB