use*_*717 17 php oop testing class object
关于在另一个类中使用类对象,最佳做法是什么?要在类_construct语句中传递类对象还是创建一个新的类对象?
例1:
class Foo {
private $bar;
public function __construct($bar){
$this->bar = $bar;
}
}
Run Code Online (Sandbox Code Playgroud)
或者示例2:
class Foo {
private $bar;
public function __construct(){
$this->bar= NEW bar;
}
}
Run Code Online (Sandbox Code Playgroud)
我知道显然已经理所当然地认为类文件必须已经包含在其他地方,并且在第一个实例中,这种类型的类对象需要已经存在,但我想知道每个方法的优点是什么,因为我有很多类需要编写使用数据库对象的类,我需要最好的方法将它传递给类.还有第三种选择比这两种选择更好吗?
根据我的理解,第一个的优点可能是少一些编码行,而在DB的情况下,没有创建新的连接.第二个可能会更好,但因为它更自包含?无论如何我以为我会问专家.
Mad*_*iha 13
首先.(这种方法称为依赖注入).
构造函数询问问题中的对象需要什么才能工作.这样,从单独的方法(他们需要什么,他们返回什么),它做了什么,它是非常清楚的.甚至没有查看源代码.
改进代码的一种方法是在方法中引入类型提示:
class Foo {
private $bar;
public function __construct(Bar $bar){
$this->bar = $bar;
}
}
Run Code Online (Sandbox Code Playgroud)
这样只能Bar
传入对象.
*免责声明:在这个答案的表现中没有小猫受到伤害
Jvd*_*erg 10
您应该选择选项1,因为这是最简单的依赖注入形式.
在选项1中:
一般情况下,我会与DI人群联系,原因在于如何考虑关于单元测试的"新"操作员:
但是,依赖注入如此重要的原因是在单元测试中,您希望测试应用程序的一小部分.要求是您可以独立于整个系统构建应用程序的这个小子集.如果将应用程序逻辑与图形构造(新运算符)混合,则除了应用程序中的叶节点之外,任何其他内容都不可能进行单元测试.
将代码分离为创建者图和协作者图将有助于保持代码的可维护性和可测试性.更好的是,针对接口的代码将很容易与其他实现交换具体实现.这使得更改代码变得简单,因为您不必通过代码搜索硬编码的依赖项.
例如,假设您Bar
需要记录器,那么您可以这样做
class Foo
{
private $logger;
public function __construct(LogInterface $logger)
{
$this->logger = $logger;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你传递实现它的任何具体实现LogInterface
,比如数据库记录器或StdOutLogger,或者包含这两者的复合记录器.另一个例子是Database对象.您可以在引导程序中创建一次,然后将其传递给使用它的对象.
如有疑问,请使用依赖注入.
但是,你并不总是需要注入东西.这取决于对象(您的Bar)是Injectable还是Newable.引用Misko Hevery:
Injectable类可以在其构造函数中请求其他Injectable.[...]注射器往往具有接口,因为我们可能不得不用对测试友好的实现来替换它们.但是,Injectable永远不能在其构造函数中请求非Injectable(Newable).这是因为DI框架不知道如何生成Newable.[...] Newables的一些例子是:Email,MailMessage,User,CreditCard,Song.如果你保持这种区别,你的代码将很容易测试和使用.如果您违反此规则,您的代码将难以测试.
简而言之,当您拥有无法合理注入的内容时,因为它基于用户提供的或运行时信息,您可以使用new
它.对于值对象和数据类型尤其如此:
class Foo
{
private $storage;
public function __construct()
{
$this->storage = new SplObjectStorage;
}
}
Run Code Online (Sandbox Code Playgroud)
注射没有意义SplObjectStorage
.它只是一种数据类型.