Skip to content

Categories:

The “Service Locator” software design pattern is an Object UNoriented fad

The Object Oriented Programming (OOP) methodology has origins dating back to the 1950s, but revolutionized the software industry when it became the dominant programming methodology in the 1990s.  It has continued to dominate to this day where it remains the foundation of all of modern major software development languages including C++, Java, Ruby, PHP5, and many more.  OOP is universally accepted as the best-practice methodology for software development across the majority of computing platforms and provides developers with a unique approach to software design that elegantly mimics real world concepts through the use of objects.

Service Locator is a serivces oriented design pattern which misappropriates concepts of the Services Oriented Architecture (SOA) paradigm.  SOA arose from a need to integrate discreet systems that were built independently using incompatible technologies (eg: EJB and CORBA) across networks.  It revolutionized software integration and has facilitated countless integrations of otherwise completely incompatible systems and platforms.  SOA concepts work extremely well when applied to the software integration space, however a services oriented architecture has no place in application development.  The Service Locator pattern capitalises on the success of SOA by tapping into the hype around services oriented architecture, but the problem is it applies the concepts in the wrong context, in the same way a screwdriver is an excellent tool for fastening a screw, but not for a nail.  A software application by definition is a tailored package of software components specifically designed to work together in providing a set of functionality.  There are no incompatible technologies as the software developer carefully chooses the components that are used.  A services oriented design approach, and therefore a Service Locator pattern is not required, not useful, and is generally counter-productive.

By its very name, everything in OOP is oriented around the concept of an”Object”. The Service Locator pattern breaks this pattern by orienting everything around the concept of a “Service”. “Model” objects within the Service Locator pattern (ie: objects representing domain entities) are generally reduced to dumb containers for data offering little advantage over primitive structures such as arrays. Service Locator pundits stress to never allow domain objects the ability to know about the service manager, causing these objects to become detached, powerless, and oblivious of the wider system in which they reside. Even the relationship between domain objects and the software developer becomes fragmented as the Service Locator pattern relies on Services to do just about everything.

This is in direct conflict with the most fundamental of OOP principles which require that objects interact with each other and specifically are able to “do” useful things (ie: perform actions) via methods above and beyond simply getting and setting their own attributes.  A classic example is the “Car” object which has the methods “Drive” and “Stop”.  A car is a complex machine with many many internal parts (pistons, spark plugs, camshaft, etc), however car drivers are not generally concerned with all of this as the car does a great job of abstracting away all of its complex internal components into a simple method “Drive” which is invoked by the driver depressing one pedal (or invoking one method).  The Service Locator pattern breaks this so that a car no longer knows how to drive.  In fact, even the spark plugs no longer know about the pistons.  Instead, objects become little more than a catalogue of parts which rely on a service to instantiate and assemble them in the same way a puppeteer pulls the strings on a puppet.  In OOP, objects were never intended to be merely puppets.

The Service Locator pattern wraps and proxies the highly structured and namespaced class hierarchy system offered by OO languages with what’s essentially and unstructured, global key/value pair system that offers no advantage except to satisfy someones perverted desire to implement the Service Locator pattern.  Global variables are generally avoided in software development due to several problems they introduce into a system, especially around security and scope.  Services stored in the global registry are generally done so in a loosely-typed fashion which is not only at odds with OOP principles but compromises the strongly typed qualities of languages like C# and Java.

The Service Locator pattern violates the Interface Segregation Principle of the SOLID set of Object Oriented Design principles which states that “clients should not be forced to depend on methods they do not use”.  It’s impossible for the Service Locator design pattern to satisfy this as the Service Manager can expose any number of method signatures globally to the entire application, and these can be changed at any time without detection at compile-time, thereby resulting in run-time errors.

The Service Locator software design pattern is an object UNoriented fad that will disappear into obsolescence as more and more people speak out against it and its related concepts.  Personally, I think that can’t come soon enough.

Posted in Uncategorized.


One Response

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Glenn Schmidt says

    I don’t love this pattern either, but I disagree with some of your arguments against it.

    The part I do agree with is that the service locator is a loosely-typed repository, and this makes it harder to write reliable software. Services are referred to by arbitrary string keys, so the service dependencies in an application are not known by the compiler and can never be validated, even in a strongly-typed, compiled language like Java. Failing to find an expected service object, or finding the wrong type of object in the repository, will always be a runtime error. That’s the biggest issue with the service locator pattern. Unless you are highly disciplined with naming and namespacing your service keys, and are building a very extensible system with a lot of optional plug-in modules, this pattern probably does more harm than good.

    I disagree, though, that the pattern forces you to have a passive model layer. You can manage your models however you like. You wouldn’t provide the service locator to your models, but that doesn’t mean you can’t provide them with other objects they need, such as a reference to the datastore service or database connection they came from.

    It’s also wrong to say the pattern is bad just because it creates a global namespace where certain objects live. No matter how you choose to build up your application’s object graph, the root-level objects will always need to be stored somewhere. It could be an ‘application’ class of some kind, a service manager / registry as discussed here, or the singleton / static method pattern. These alternatives all provide some kind of ‘global’ or app-wide mechanism for obtaining access to core services.

    myApp->getLog()
    services->get('Log')
    Logger::getInstance()

    Again, the only real disadvantage of the service registry compared to the other options, is that it’s loosely typed. You can’t be sure that the ‘Log’ service will exist, and you will have to cast the result to the appropriate class at runtime. That’s what sucks about a service locator.