【发布时间】:2016-02-03 10:30:31
【问题描述】:
根据 Marco 对 this 的 Pivetta 想法,这个 old question 以及我对an other question的回答@
我一直在问自己如何在 Zend Framework 2 应用程序中使用我们的服务。
实际上我们可以将ServiceLocatorAwareInterface 与ServiceLocatorAwareTrait 结合使用。
鉴于In ZF3 service locator will be removed in controller 的事实,他们可能还会删除此接口,或者建议不使用它的人,这是有道理的。
我了解如何构建我们的服务的唯一方法是:
不要在你的服务中使用 ServiceLocator,使用 DependancyInjection。
问题是:
有些项目太大了,你有:
- 一个工作流的 15 个服务类。
- 具有 15 个依赖项的服务类。
- 选择你的噩梦...
一些您可能需要的服务示例:
- 取回formManager(不能在控制器中调用)
- 在通过 AJAX 和 JSON 响应将 HTML 字符串返回到视图之前,您可能需要让 ViewRenderer 呈现模板;
- 您可能需要取回翻译器或您希望 ZF2 提供的每项服务
- 获取您的实体管理器,如果您有多个数据库,请在此处添加计数
- 获取 MailService、ExportService、ImportService 等其他服务...
- 如果您必须加载特定服务取决于客户端(BtoB 中的多客户端网站...添加一些服务,因为您无法加载 | 调用 AbstractFactory)
也许对于其中一些问题,它们可以通过我不知道的技巧来解决。
我的问题是:
为一项服务拥有 15 个或更多依赖项是否是一种好习惯 并放弃 ServiceLocator,在控制器中,也在服务中?
从 cmets 编辑
为了说明我的观点,我粘贴了一个构造函数:
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();
}
如您所见,ToolboxService 本身就是一个具有多个依赖项的对象。该服务在我的应用程序文件夹中,几乎无处不在。 我有 2 个实体管理器(连接到 2 个数据库,但也许很快,我需要第三个......)
您可以看到我通过依赖关系使用 serviceLocator,因此该服务没有实现 ServiceLocatorAwareInterface。如果我不使用它,我会为我的 AbstractFactory 调用而彻底搞砸
// 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);
}
【问题讨论】:
-
你能给出一个有 15 个硬依赖的服务的具体例子吗?我会说,如果是这样的话,应该更多地以不同的方式组织事情......
-
组织的问题,我已经有想法了。当您拥有庞大的应用程序,经过多年的开发,再加上多客户端应用程序,您必须使用通用工作流程处理所有这些应用程序,然后处理特定性。ServiceLocator 可以很好地实现这一目标
-
我认为您可以将这些
UserService|ItemService|EntityService分组为ResourceService和Import|Export中的ExchangeService或TransportService。然后你有5个依赖项。但也许这不是您正在等待的评论:D -
将依赖分组并不是解决方案,因为每个服务可以相互独立,甚至属于不同的模块。用户和项目分为 2 个不同的模块。我的模块订单有 3 个依赖项:应用程序/用户/项目。另外,分组依赖关系在架构方面没有更多作用,它只是隐藏了混乱。
-
我在这里同意@Wilt;您可以进一步将多个服务封装为一个,从而减少依赖项的数量。这些新服务将只是相关服务的容器(也是注入的),因此它们仍然可以单独使用。
标签: php architecture zend-framework2