ServiceLocator, think about it in the context of ZF2

According to Marco Pivetta’s thought with this , this old question and my answer to another question

I interrogated myself about how best to use our services in a Zend Framework 2 application.

In fact, we can use ServiceLocatorAwareInterface in combination with ServiceLocatorAwareTrait . With fact In ZF3, the service locator will be removed in the controller . Perhaps they will also remove this interface or advise people who do not use it, it makes sense.

The only way I see how our services can be designed is:

Do not use ServiceLocator in your Services, use DependancyInjection.

The problem is this:

Some projects are so large that you have:

  • 15 classes of services for one workflow.
  • A class of service with 15 dependencies.
  • Choose your nightmare ...

An example of what you might need in a service:

  • Return formManager (you cannot call it in the controller)
  • You may need your ViewRenderer to render the template before returning the HTML string to the view via AJAX and a JSON response;
  • You may need to return the translator or any service you want to provide ZF2
  • Get an object manager, if you have several databases, add an account here
  • Get other services like MailService, ExportService, ImportService, etc.
  • If you need to download specific services, it depends on the client (a multi-client website in BtoB ... adds somes services because you cannot load | an AbstractFactory call)

Perhaps for some of these points they can be solved with tricks that I do not know.

My question is:

Is it good to have 15 or more dependencies for one service? and abandon ServiceLocator, in controllers, but also in services?

Edit Comment

To illustrate my point, I insert one of my constructors:

 public function __construct( ToolboxService $toolboxService, EntityService $entityService, UserService $userService, ItemService $itemService, CriteriaService $criteriaService, Import $import, Export $export, PhpRenderer $renderer ) { $this->toolboxService = $toolboxService; $this->entityService = $entityService; $this->userService = $userService; $this->emOld = $this->toolboxService->getEmOld(); $this->emNew = $this->toolboxService->getEmNew(); $this->serviceLocator = $this->toolboxService->getServiceLocator(); $this->itemService = $itemService; $this->criteriaService = $criteriaService; $this->import = $import; $this->export = $export; $this->renderer = $renderer; $this->formManager = $this->toolboxService->getFormManager(); } 

As you can see, ToolboxService is an object with several dependencies. This service is in my application folder and almost everywhere. I have 2 object managers (connecting to 2 databases, but maybe soon I will need a third ...)

You can see that I use serviceLocator through a dependency, so this service does not implement ServiceLocatorAwareInterface . If I do not use it, I am lyrically screwed to my AbstractFactory call with

 // Distribute somes orders depends on Clients $distributionClass = $this->serviceLocator->get(ucfirst($param->type)); if ($distributionClass instanceof DistributeInterface) { $distributionClass->distribute($orders, $key); } else { throw new \RuntimeException("invalid_type_provided", 1); } 
+5
source share
1 answer

Say you introduce an instance of ServiceLocator . There is no guarantee that ServiceLocator really contains your hard dependencies, thereby violating the DI pattern. When using constructor dependency injection, you are sure that all the necessary services are indeed available. If not, then building the service will simply fail.

When using ServiceLocator you will end up in an instance service class where hard dependencies may or may not be available through ServiceLocator . This means that you need to write all the additional logic (check dependencies, exclude exceptions) in case the dependency cannot be resolved from the ServiceLocator instance at the moment you ask for it. Writing all of this code is likely to be much more time consuming than injecting 15 dependencies, and moreover, the logic will clutter up your entire service.

In addition, you still need to add all the setter and getter methods to get your services from your ServiceLocator and make your service validate.

IMHO, introducing 15 dependencies, less code and easier to maintain, and then introduces an instance of ServiceLocator .

+3
source

Source: https://habr.com/ru/post/1235106/


All Articles