Oop 如何进行依赖注入';d代码是否适合使用和测试?
我刚开始学习PHP,如果我做错了什么,请原谅我的代码。Oop 如何进行依赖注入';d代码是否适合使用和测试?,oop,design-patterns,language-agnostic,dependency-injection,Oop,Design Patterns,Language Agnostic,Dependency Injection,我刚开始学习PHP,如果我做错了什么,请原谅我的代码。 让我们看看我对一个“保险”对象的这种方法,它会把所有说保险的客户都还给我: public function getBeneficiarios() { $petitionsVariables = array( PeticionDeCoberturaColumns::COBERTURA_ID => $this->getId() ); $petitions = (
让我们看看我对一个“保险”对象的这种方法,它会把所有说保险的客户都还给我:
public function getBeneficiarios() {
$petitionsVariables = array(
PeticionDeCoberturaColumns::COBERTURA_ID => $this->getId()
);
$petitions = (new PeticionDeCoberturaDAO())->getByValues($petitionesVariables);
$clientes = array();
foreach ($petitions as $petition) {
$clientes[] = $petition->getClient();
}
return $clientes;
}
所说的代码显然不太可测试,因为它耦合到特定的DAO。为了正确地测试它,我需要模拟DAO并注入模拟
依赖注入的方法应该是
public function getBeneficiarios($dao) {
$petitionsVariables = array(
PeticionDeCoberturaColumns::COBERTURA_ID => $this->getId()
);
$petitions = $dao->getByValues($petitionesVariables);
$clientes = array();
foreach ($petitions as $petition) {
$clientes[] = $petition->getClient();
}
return $clientes;
}
我可以将DAO注入保险对象构造函数中,但我不喜欢只传递不相关的DAO,因为它需要在单个方法中使用 每次我想使用getBenegianIOS方法时,我都需要首先创建DAO,这听起来非常非常违反直觉。未来的程序员不应该为此烦恼
我怎样才能既保持舒适的代码使用,又保持舒适的代码测试 在我看来,问题不在于类的可测试性,而在于应用程序的设计 在真正的DDD中,您的类不应该依赖DAO,甚至不应该知道它的存在。你可以称之为坚持无知。保险对象唯一应该知道的是当事人(客户、保险公司)和其他商业概念,如法律条款 封装最重要的一点是,类的使用者不需要知道它在其他语言中的内部工作,就可以成功地使用它。让保险依赖于静态DAO对象会破坏封装,因为其使用者需要知道静态DAO必须存在于某个地方,否则将发生异常 DAO是一个实现细节。您的域对象不应该依赖于或了解它,它应该依赖于您的域对象。IoC是确保更基本事情的一种手段,例如关注点分离和封装。如果你的设计违反了这些规定,那么国际奥委会将无法解决。作为起点,我将从DDD的角度来看我的设计。请看以下问题:
让我知道这是否有帮助。在我看来,您的问题不是类的可测试性,而是应用程序的设计 在真正的DDD中,您的类不应该依赖DAO,甚至不应该知道它的存在。你可以称之为坚持无知。保险对象唯一应该知道的是当事人(客户、保险公司)和其他商业概念,如法律条款 封装最重要的一点是,类的使用者不需要知道它在其他语言中的内部工作,就可以成功地使用它。让保险依赖于静态DAO对象会破坏封装,因为其使用者需要知道静态DAO必须存在于某个地方,否则将发生异常 DAO是一个实现细节。您的域对象不应该依赖于或了解它,它应该依赖于您的域对象。IoC是确保更基本事情的一种手段,例如关注点分离和封装。如果你的设计违反了这些规定,那么国际奥委会将无法解决。作为起点,我将从DDD的角度来看我的设计。请看以下问题:
让我知道这是否有帮助。“我可以将DAO注入保险对象构造函数,但我不喜欢传递不相关的DAO的想法,因为它需要在单个方法上使用。”-如果类只需要DAO的一个子集,其功能小到足以让您认为它是不相关的,也许它应该被分开。也就是说,“使用舒适”和“测试舒适”似乎是不一致的。好的、松散耦合的因式分解往往会导致许多高度专业化的类,这些类天生就很难连接在一起,更难以完全理解。您通常通过将这种细粒度的结构作为一个实现细节,并在其上分层一个更方便的API表面来应对这种情况。是的,这是一个选项。使用更正式的术语,您原来的类似乎违反了单一责任原则。就我个人而言,我倾向于将finder方法放在DAO层,除非DAO是不可定制的。这似乎是过度使用方法注入。如果
ClientFinder
是无状态的,只需在脚本启动时创建一个,并将DAO传递给构造函数即可。显然,您还应该将保险对象注入客户机查找器。这样的话,保险对象(如果我正确理解的话)是一个“胖模型”对象,它也可以作为其他架构层的API门面。我认为我们已经到了答案很可能是“这取决于”。如果您有几种不同的方法来查找客户(即通过保险应用程序检索客户,或直接按城市筛选客户),那么有一个单独的类来处理这个问题是有意义的。通常,客户机DAO足以做到这一点,但在您的模型中,事情似乎更复杂。因此,如果您不想将所有这些逻辑都移动到客户机DAO中,那么创建一个包含请愿DAO和城市DAO的ClientFinder
是一个不错的选择。“我可以将DAO注入到保险对象构造函数中,但我不喜欢传递无关DAO的想法,因为它需要在单个方法中使用。”-如果类只需要DAO来实现其功能的一个子集,其小到足以让您认为它是不相关的,那么可能应该将其拆分。也就是说,“使用舒适性”和“测试舒适性”似乎是不一致的。好的、松散耦合的因式分解往往会导致许多高度专业化的类,这些类天生就很难连接在一起,更难以完全理解。您通常通过将这种细粒度的结构作为实现细节和层来应对这种情况