Php 依赖注入总是正确的答案吗?
我现在正在考虑很多关于依赖注入的问题,它是赞成和反对的。一般来说,似乎有一种共识,即依赖注入在大多数情况下都是正确的选择。我看到了它的方便之处,以及它如何使代码更具可读性。因此,我试图用尽可能多的依赖注入来创建我的类,将关注点分离为多个对象。在我70%的日常工作中,这很好。它起作用了,我看到了它的好处 然而,剩下的30%让我有点挣扎。我对依赖注入本身的概念没有问题,但我认为PHP确实有一些“特殊属性”,这让我怀疑依赖注入是否是正确的选择Php 依赖注入总是正确的答案吗?,php,dependency-injection,service-locator,Php,Dependency Injection,Service Locator,我现在正在考虑很多关于依赖注入的问题,它是赞成和反对的。一般来说,似乎有一种共识,即依赖注入在大多数情况下都是正确的选择。我看到了它的方便之处,以及它如何使代码更具可读性。因此,我试图用尽可能多的依赖注入来创建我的类,将关注点分离为多个对象。在我70%的日常工作中,这很好。它起作用了,我看到了它的好处 然而,剩下的30%让我有点挣扎。我对依赖注入本身的概念没有问题,但我认为PHP确实有一些“特殊属性”,这让我怀疑依赖注入是否是正确的选择 使用DI而不是服务定位器的主要观点似乎是,您有“编译时错误
类记录处理程序{
//使用特征启用对getInstanceOf()方法的访问,
//它是指向服务容器singleton的全局实例的链接
使用ContainerWareTrait;
/**
*@var EnvService
*/
受保护的服务;
/**
*RecordHandler构造函数。
*
*@param EnvService$EnvService
*/
公共功能构造(EnvService$EnvService){
$this->envService=$envService;
}
//…其他方法。。。
公共函数filterRecords(数组$记录):数组{
//使用普通DI对象。。。
如果($this->envService->isStaging()){
//做些不同的事。。。
返回[];
}
foreach($recordId=>$record的记录){
//这可能发生在10%的时间里。。。
//我不知道这里的数据库是否已经连接。
//在容器中注册的工厂将在创建对象时初始化连接。。。
如果(空($记录)){
$record=$this->getInstanceOf(DbService::class)->查询(“从'stored_record_table中选择*,其中id=?”,[$recordId]);
}
//这可能发生,但在50%的情况下不会发生。。。
如果(!empty($record[“xmlField”])){
$record[“xmlField”]=$this->getInstanceOf(XmlService::class)->handleXml($record[“xmlField”]);
}
//正在基于记录的值创建类实例。。。
如果(!empty($record[“classField]”)和&class_存在($record[“classField]”)和&
在数组中(HandlerInterface::class,class_实现($record[“classField”])){
$i=$this->getInstanceOf($record[“classField]”);
$i->handle($record);
}
}
}
请注意,EnvService和DbService在使用过的服务容器中被标记为“Singleton”,这意味着一旦它们被创建,容器将一次又一次地返回相同的实例
我真的很想看看是否有更好的解决方案,因为我使用了多种解决方案进行了测试,这样做可以节省30-50%的执行时间,而执行时间的波动取决于所处理的记录类型
此外,我也意识到了隐藏依赖项等缺点。为了防止这个问题,我尝试创建“上下文对象”,它们基本上是硬编码的DI容器,但它们似乎也不是选项
最后,我尝试使用“延迟加载”为了避免上述问题,例如PHP-DI在其文档中明确指出,您不应该为超过3-4个类创建延迟加载代理,这似乎没有多大帮助。没有模式始终是答案;在不能延迟的情况下,做出明智、实用的架构决策非常重要 您说得对,在PHP的情况下,由于每个请求都必须实例化整个对象图,DI可能会导致性能损失 然而,依赖注入显然与性能无关