【问题标题】:Dependency injection unneeded services [closed]依赖注入不需要的服务
【发布时间】:2019-10-23 13:01:52
【问题描述】:

假设我们正在使用一些依赖注入,并且我们在一些控制器中使用它。

例如 Laravel 或任何其他具有 DI 的框架(在这种情况下与 PHP 无关)。

假设我们有这个控制器:

class UserController extends Controller
{
    public function __construct(UserRepository $users, Mailer $mailer, Logger $logger)
    {
        $this->users = $users;
        $this->mailer = $mailer;
        $this->logger = $logger;       
    }
    public function method1(){...}
    public function method2(){...}
    public function index(UserRepository $users){...}
}

每个人都说这是个好设计,但我的问题是:

如果控制器调用 method1 并且它仅使用 ma​​iler,那么构造具有所有 3 个依赖项的对象有什么意义。即使不占用大量内存或性能,这不是最优的吗?

有人会认为这个控制器需要所有这些,但实际上如果我只调用 method1,它只需要 ma​​iler。 p>

如果我尝试在“index”方法之类的方法上注入依赖项,我该怎么做,因为如果我扩展相同的方法并需要不同的依赖项,PHP 会因为方法签名不同而崩溃。

处理此问题的最佳方法是什么。

如果我在单独的控制器中提取每个方法,我将不得不做很多重复。

谢谢

【问题讨论】:

  • 我的意思是这两种方法都以 $userId 为例,但在 UserController 我需要 Logger 服务,所以我不能将它作为参数添加到要注入的方法中 - 它需要在构造函数中注入,但是这样,其他控制器方法中可能不需要此服务。
  • 你要么需要在构造函数中注入它,要么为它创建一个新方法。真的没有办法解决这个问题。如果该方法与父方法具有不同的依赖项/签名,则无论哪种方式,它都应该是它自己的方法。
  • “最佳方式”的客观指标是什么?

标签: php dependency-injection


【解决方案1】:

有几点需要考虑:

  • 首先,当injection constructors are simple 时,并不是所有的依赖关系都一直被使用应该没关系。这不应导致任何可衡量的性能损失,因为性能瓶颈通常是由 I/O 引起的。
  • 但是,如果您的类包含许多依赖项,并且有许多仅在某些方法中使用的依赖项,则可能表明该类上的方法没有内聚性。这又可能表明该类违反了单一责任原则。换句话说,这个类可能太大了,有多个职责,如果是这样的话,它应该被分成多个更小的类。围绕实体概念(例如UserController 所做的)对类功能进行分组通常是违反 SRP 的原因。相反,更好的解决方案通常是围绕功能对类进行分组。例如DeleteUserControllerPromoteUserControllerBlockUserController

【讨论】:

  • 谢谢,一个问题在于测试 - 我必须提供所有依赖项或 4 个模拟对象来测试一种方法,即使它只使用 1 个依赖项。但也许它最终没有那么大的问题。
  • 有些模式可以帮助您简化测试。例如,看看这个sut factory pattern。但同样,如果您的类的方法没有凝聚力,则表明该类违反了单一职责原则。
  • 谢谢,可以这样设置参数吗 (logger = di('logger') - di 是从容器返回记录器对象的全局函数,否则这是不好的做法
  • 这似乎是服务定位器反模式的变体。
猜你喜欢
  • 1970-01-01
  • 2020-09-09
  • 2020-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
相关资源
最近更新 更多