【问题标题】:When to instantiate a new class inside my controller and when to inject that class as a dependency?什么时候在我的控制器中实例化一个新类,什么时候将该类作为依赖注入?
【发布时间】:2017-07-18 15:42:48
【问题描述】:

我什么时候使用new 在我的控制器中创建任何类,我什么时候注入该类到我的控制器中?

例如,假设我有一个AnnotationBuilder 类(它通过读取域实体内的注释来构建一个Zend\Form 对象)。

我可以像这样在我的控制器中调用它:

$form = (new AnnotationBuilder())->createForm(MyForm::class);

或者我可以将AnnotationBuilder 的实例传递给我的控制器并像这样调用它:

$form = $this->annotationBuilder->createForm(MyForm::class);

或者如果我将AnnotationBuilder直接传递给方法,我可以使用:

$form = $annotationBuilder->createForm(MyForm::class);

对此有什么指导方针吗?例如,阅读依赖注入时,我可以大胆猜测必须声明我的所有依赖项,并且由于AnnotationBuilder 是构建表单所需的部分,我可能可以将其注入到我的控制器的构造函数中。或者作为 setter 方法。

其他课程呢?目前在我现有的控制器中,我可以算出大约 6 个new 操作员。我是否盲目地将它们重构为全部传递到控制器中?

在控制器中使用new 创建东西是否可以接受?

【问题讨论】:

  • 将实例传递给一个类可以让您更好地测试您的类,允许您创建无法直接测试的类的模拟。
  • 我认为 new 对于值对象是可以接受的。作为旁注,切勿盲目重构,除非您有 300% 的测试覆盖率。例如对象是通过引用传递的,如果您的容器在多次调用中重用同一个对象,您可能会遇到一些脏状态。

标签: php oop dependency-injection instantiation


【解决方案1】:

这取决于模型层的复杂程度。在AnnotationBuilder 的情况下,我肯定会将它作为依赖项传递,但不一定在控制器中。我不是 Zend 用户,也不知道它实际上做了什么,但这听起来像是“输出内容”,应该放在 View 实例中(如果你有这些,而不仅仅是愚蠢的模板)。

一般来说,我会编写代码,其中控制器仅与模型层的各种服务交互。而且由于这些服务在每个运行时都是单一的,因此最好将它们作为依赖项传递。

但在每个服务中,我会处理各种实体(域对象)。而且,虽然每个运行时只有一个Authentication 服务,但它可能会管理多个Identity(或Account)实体。这些“重复实例”我会作为依赖项传递。相反,我会使用 new 运算符或使用某些工厂创建它们(这将是一个依赖项,用于单元测试目的)。

希望对你有帮助。

【讨论】:

  • Zend\Form 涵盖了所有内容 -> 我使用 AnnotationBuilder 构建表单(它使用我的域对象来创建表单对象本身),然后用值填充表单(有时从数据库中提取这些值) ,然后我将完成的表单传递给视图,视图负责将其呈现为 HTML。
  • 也就是说,AnnotationBuilder 是一个瞬态对象。它用于构建某些东西,然后被丢弃。这就像一个工厂。我可以将它完全移出控制器并在其他地方构建表单,然后将表单注入控制器......
【解决方案2】:

我不认为仅仅因为有人这么说就遵循规则是一个好主意。有理由这样做很重要。

注入东西和实例化有什么关系?

我发现它更重要的场景是单元测试。您对控制器进行单元测试?如果是,AnnotationBuilder 是您想要模拟的东西,因为它会影响性能或其他原因?

除了测试用例,有这个具体的依赖是个问题,或者你应该注入它的抽象?对于最后一个,一般来说,我看不出控制器的问题取决于具体情况,因为它只是您的应用程序的基础设施入口点。

【讨论】:

    猜你喜欢
    • 2016-01-31
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    相关资源
    最近更新 更多