【问题标题】:Should the new keyword be avoided in favour of another pattern (for example factory)?是否应该避免使用 new 关键字以支持另一种模式(例如工厂)?
【发布时间】:2017-05-19 19:58:20
【问题描述】:

来自 Google 的干净代码谈话的This videonew 不利于测试,乍一看似乎是合理的。

什么是 PHP 的好习惯?我是否应该创建一个工厂类来实例化不同的对象类型,并为每个对象类型提供一种方法,从而允许松散耦合?或者使用单一方法来初始化 new 实例的通用初始化方法(自动加载器?)会更合适,尽管后者没有指定返回类型,这使得 IDE 的代码完成在黑暗中。

【问题讨论】:

  • 该视频时长超过 50 分钟。您能否总结一下为什么他们认为new 关键字不好?
  • TL;DR:与给定的类名紧密耦合并且极难测试

标签: php oop model-view-controller


【解决方案1】:

嗯。视频是正确的。每当您在代码的一部分中包含new 时,都会使测试变得更加困难。基本上,没有办法将您正在测试的东西与该类隔离开来。这意味着您需要全面覆盖该类(您在 new 语句中拥有的那个),您的单元测试才能真正可靠。

绝对最好的选择是将所有实例作为依赖项传递(在类或方法中),但通常只在某些特定层中有效。例如,如果写得正确,很容易让你的控制器摆脱任何new 语句。您只需在构造函数中将服务作为依赖项传递,并在“动作调用”中传递Request 抽象或显式值。

因此,传递依赖项(可能通过使用一些 DI 容器)是最好的方法。也是最容易测试的一种。但这不会普遍可用。

您的其余代码可能最终(至少 - 部分地)包含new 运算符和工厂。

您可以通过在您的工厂中使用 ::class 并添加 docblock cmets 来缓解与 IDE 相关的问题:

/** @var \Mapper\SalesSomething\Invoice $invoice */
$invoice = $this->factory->create(Invoice::class);

我的个人喜好是:

  • 控制器:相关对象仅通过 DIC 作为依赖项
  • 服务:映射器的工厂,作为依赖项的存储库,new 的域实体
  • 映射器:仅依赖于构造函数
  • 实体:无依赖关系
  • 视图:相关对象仅通过 DIC 作为依赖项
  • 展示对象/小部件:通过工厂

但这只是我的方法

【讨论】:

  • 非常感谢您分享您的见解。添加 docblocks 已经为 Eclipse 解决了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-01-27
  • 1970-01-01
  • 2016-03-16
  • 1970-01-01
相关资源
最近更新 更多