It could be an instantiated class or a static class. We might call it like this:. It seems convenient. Our logic for creating class instances is hidden away inside of ServiceLocator. But there are a few big problems:. The service locator allows us to hide a dependency on absolutely anything in any method. I can do this:. This makes it far more convenient to complicate and couple code by adding random dependencies all over the place. The service locator is like a broken window.
Once one developer does it, the rest join in. Second, a class littered with calls to a service locator is difficult to test. Or, if the service locator is itself injected as a dependency, then we have to create a mock that returns more mocks, like this:.
You may have noticed that a call to a service locator looks a lot like a call to resolve something from a dependency injection container. In fact, if we were to call the container directly from most classes, then that would be using the container as a service locator. In order to properly use dependency injection, we need to control how classes are created at the composition root.
NET Core controllers are an example. They are the classes created to handle incoming requests, and at application startup we can configure them to expect injection of certain dependencies. Considering that those times were about ruling java in the world of Android, the second alternative was a complete mess. Just look at sources of Telegram. Or you can just create a multimodule system with encapsulated and isolated behavior.
Yeah, in those times there were modules too ;. But there was already the third alternative. And its name is Service Locator. Thus, it simplified development in one hand and had some issues if you use canonical pattern on another hand.
In this article we will talk about what is a Service Locator, describe its cons and will make a basic refactoring of this conception. Also, We will slightly touch some problems of dagger , kodein and why we can consider Service Locator as an alternative still nowadays at least in the begging.
The service locator pattern describes a special object which gathers all instances of services, that can be used through the whole application. In the canonical implementation, locator is passed to the instance of object to provide services for it.
It is much better to declare providing each dependency through its own separate method, which guarantees to return new instance or the cached one. Because of using kotlin we can make even more nicer approach: using properties. And if you have some external dependencies which are needed suppose for Service1 or Service2 just:.
The main problem now as it may seemed at first glance is lack of testability of a code. You can use mockk for mocking final classes which is ExampleClass , but it seems more the hack, rather the general ability of setting different test dependencies.
To resolve that in common case we can introduce a service locator as interface and hide the realisation:. Making implementation as a private class is not important for this, but I think that we always need to keep that rule with us: to hide something when it is not needed to be seen. Now, if you want to test ExampleClass, you will be able to inject a special test instance of ServiceLocator , which you will be available to make through mock libraries or just create a decorator with overriding only test instance of setvices.
But this is irrelevant to this discussion. Every subject receives a reference to the domain to which it belongs as its first constructor parameter. This is analogous to how every method of an object receives the this pointer as its first hidden parameter.
In other words, the domain is to a subject what the object is to a method. Every subject that needs to use some service obtains it from its own domain via a property of the domain. Regular getXYZ , no map lookup. The domain may offer a service directly, as in myDomain. Still, at various places where domain hierarchies are constructed, all necessary services are supplied, so any one of them can be replaced with a mock.
In lack of any better term, I am calling this Subject-Oriented Programming for the time being. Dependency injection solves a particular problem, however as you're finding it adds complexity. It's not something you should always do for everything because its 'always good', as it can actually add overhead for certain kinds of maintenance. For instance a change where you add a requirement to use a dependency in a method requires your code to change to both add an injection field to the constructor and the change where you use the dependency itself.
Dependency injection allows you to change this later. For something such as a date, if you do not envisage in any situation that your date-handling system will change which is pretty much the case for any mature programming language which provides date handling , adding dependency injection for this function has a cost and gives you nothing.
So don't do it. So if you don't need the flexibility DI gives you for some of the services you're DIing, just take them out, use a service locator or even horror a direct dependency. Its a judgement: if you later find you actually do need that flexibility, modern code dev platforms will let you add it in without too much pain. What would happen if you decide that Class A needs a different logger for example than Class B? Or even harder, if instance 1 of Class A needs a different logger than instance 2 of Class A?
You might not have this requirement now, but in the feature you might have it. Maybe you want specific classes or instances to log into different files or to use completely different logging libraries. These concerns might also be valid for the other dependencies that you want to obtain from the service locator.
You cannot solve this issue if you are using the Service Locator because the Service Locator limits composability. On the other hand, if you inject your dependencies, you have full power to compose your objects in anyway that you want.
Sign up to join this community. The best answers are voted up and rise to the top. Stack Overflow for Teams — Collaborate and share knowledge with a private group. Create a free Team What is Teams? Learn more. Is it ok to use service locator for ubiquitously used dependencies?
0コメント