服务定位,让我们一下思绪在ZF2背景 [英] ServiceLocator, let's thoughts about it in ZF2 context

查看:138
本文介绍了服务定位,让我们一下思绪在ZF2背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据Marco的Pivetta想法这个,这的老问题
而我的回答的其他问题

我询问关于自己的更好的方式来使用我们的服务在Zend Framework的应用2

其实我们可以使用 ServiceLocatorAwareInterface 结合 ServiceLocatorAwareTrait
与事实在ZF3服务定位器将在控制器被移除的这可能是可能的,他们将也删除此接口或建议人们不要使用它,它是有意义的。

我看到我们的服务是如何被构建的唯一方法是:


  

不要在您的服务使用服务定位,使用DependancyInjection。


问题是:

有些项目只是这么大,你要么:


  • 15服务的一个工作流程类。

  • 服务与15级的依赖关系。

  • 选择您的噩梦...

一些示例,您可能需要在服务的内容:


  • 找回formManager(你不能把它的控制器)

  • 您可能需要得到您的视图解析器通过AJAX的HTML字符串返回到视图之前呈现模板,JSON响应;

  • 您可能需要找回翻译,或者您希望通过提供ZF2每个服务

  • 让您的实体管理器,如果你有多个数据库,在此添加计数

  • 获取其他服务一样MailService的,ExportService,ImportService等等...

  • 如果您需要加载细节服务取决于客户端上(在的BtoB多客户的网站......添加萨姆服务,因为你不能加载|调用AbstractFactory)

也许对于一些这些点,他们可以通过一个技巧,我不知道来解决。


  

我的问题是:


  
  

它是一个很好的做法,有15个或更多的依赖关系为一个服务
  而放弃服务定位,在控制器,而且在服务呢?


从意见修改

有关说明我的观点,我贴我的构造之一:

 公共职能__construct(
    ToolboxService $ toolboxService,
    EntityService $ entityService,
    UserService $ userService,
    ItemService $ itemService,
    CriteriaService $ criteriaService,
    导入$进口,
    出口$出口,
    pH值prenderer $渲染器
){
    $这个 - > toolboxService = $ toolboxService;
    $这个 - > entityService = $ entityService;
    $这个 - > userService = $ userService;
    $这个 - > emOld = $这个 - > toolboxService-> getEmOld();
    $这个 - > emNew = $这个 - > toolboxService-> getEmNew();
    $这个 - >的ServiceLocator = $这个 - > toolboxService-> getServiceLocator();
    $这个 - > itemService = $ itemService;
    $这个 - > criteriaService = $ criteriaService;
    $这个 - >进口= $进口;
    $这个 - >出口= $出口;
    $这个 - >渲染器= $渲染器;
    $这个 - > formManager = $这个 - > toolboxService-> getFormManager();
}

正如你所看到的,ToolboxService是一个多依赖关系本身就是一个对象。该服务在我的应用程序文件夹中,几乎无处不在。
我有2个实体管理器(连接到2个数据库,但也许不久,我将需要第三个......)

您可以看到,我使用的ServiceLocator throught一个依赖关系,因此该服务并不农具 ServiceLocatorAwareInterface 。如果我不使用它,我literraly拧我的电话AbstractFactory以

  //分发萨姆订单取决于客户端
$ distributionClass = $这个 - > serviceLocator->得到(ucfirst($参>类型));
            如果($ distributionClass的instanceof DistributeInterface){
                $ distributionClass->分发($订单,$键);
            }其他{
                抛出新的\\的RuntimeException(invalid_type_provided,1);
            }


解决方案

比方说,你会注入的ServiceLocator 实例。有没有保证,的ServiceLocator 实际持有硬盘的依赖,从而打破了DI模式。当使用构造函数依赖注入你是确保所有需要的服务是真正可用。如果不是,该服务的构建只会失败。

在使用的ServiceLocator 你会在一个实例化服务类结束了在那里辛勤的依赖可能会或可能不会是可以通过的ServiceLocator 。这意味着你必须写各种额外的逻辑(检查依赖,抛出异常)的情况下,依赖关系不能从的ServiceLocator 比如你问的那一刻得到解决。写这一切code可能会更加的工作,然后注入15依赖性和对的逻辑将所有堆满了您服务。顶部

此外,你还需要添加所有的setter和getter方法​​,以便能够从你的的ServiceLocator 让你的服务,使您的服务测试。

恕我直言,注入15的依赖较少code和易于维护,然后注入的ServiceLocator 实例。

According to Marco's Pivetta thoughts with this, this old question and my answer to an other question

I was interrogating myself about the better way to use our Services in Zend Framework 2 application.

Actually we can use the ServiceLocatorAwareInterface combined with ServiceLocatorAwareTrait. With the fact In ZF3 service locator will be removed in controller It may be possible that they will also remove this interface, or advice people not using it, it make sense.

The only way I see how our Services may be constructed is :

Don't use ServiceLocator in your Services, use DependancyInjection.

The problem is :

Some project are just so big that you have either :

  • 15 services's class for one workflow.
  • A service's class with 15 Dependancies.
  • Pick your nightmare...

Some example for what you may need in a service :

  • Get back the formManager (you can't call it in the controller)
  • You may need to get your ViewRenderer to render template before returning an HTML string to the view through AJAX, and JSON response;
  • You may need to get back the translator or every service you want provided by ZF2
  • Get your entity Manager, if you have multiple database, add count here
  • Get others service like MailService, ExportService, ImportService and so on...
  • If you have to load specifics services depends on a client (multi-client website in BtoB... add somes services, because you can't load | call an AbstractFactory)

Maybe for some of those points, they're can be solved by a tricks that I don't know.

My Question is :

Is it a good practise to have 15 or more Dependancies for one service and give up the ServiceLocator, in controllers, but also in services ?

Edit from comments

For illustrate my point, I paste one of my constructor :

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 multiple dependancies itself. This Service is in my Application folder, and almost everywhere. I have 2 entity Managers (connection to 2 databases, but maybe soon, i will need a third one...)

You can see that I use the serviceLocator throught a dependancy, so this service doesn't implements ServiceLocatorAwareInterface. If I'm not using it, i'm literraly screwed for 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);
            }

解决方案

Let's say you would inject the ServiceLocator instance. There is no guarantee that the ServiceLocator actually holds your hard dependencies, thus breaking the DI pattern. When using constructor dependency injection you are sure that all the services that are needed are really available. If not, the constructing of the service will simply fail.

When using a ServiceLocator you will end up in an instantiated service class where hard dependencies might or might not be available through the ServiceLocator. This means you have to write all kind of additional logic (check dependencies, throw exceptions) in case the dependency cannot be resolved from the ServiceLocator instance the moment you ask for it. Writing all this code will probably be much more work then injecting 15 dependencies and on top of that the logic will be cluttered all over your service.

Additionally you would still need to add all the setter and getter methods to be able to get your services from your ServiceLocator and to make your service testable.

IMHO injecting 15 dependencies is less code and easier to maintain then injecting a ServiceLocator instance.

这篇关于服务定位,让我们一下思绪在ZF2背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆