避免注入服务容器而不是单个服务的技术原因是什么?

Ste*_*nte 15 php dependency-injection symfony

通常,当我需要将一个或多个服务注入另一个服务时,我会明确注入每个服务.但是,我有一种情况,注入服务容器本身将使事情变得更容易.我知道这不是推荐的做法,但我很好奇技术原因是什么阻止了这一点.它是合法的,因为它太资源密集,或者更个人的感觉,它太乱了?

Rya*_*ndy 23

如果注入容器,则不会清除依赖项.事实上,你比以前更加模糊他们.如果你有这样的课......

class DocumentCreator(IFileNamer fileNamer, IRepository repository)
{ ... }
Run Code Online (Sandbox Code Playgroud)

...你可以看到依赖是什么.您还可以轻松地模拟这些依赖项以进行单元测试,以确保您隔离DocumentCreator并且可以知道任何测试失败都是由其代码而不是其依赖项中的代码造成的.

另一方面,如果你这样做......

class DocumentCreator(IDependencyContainer container)
{ ... }
Run Code Online (Sandbox Code Playgroud)

......你掩盖了依赖关系.如果不检查类的内部,你不可能知道它需要一个IFileNamer和一个IRepository.

您也不能轻易知道需要将哪些模拟放入容器中以测试DocumentCreator.模拟IDependencyContainer根本不会帮助你; 您的类仍然会在测试中失败,因为容器不包含IFileNamer和IRepository,除非您检查类的内部以查看它们是否是必需的.


Seb*_*ber 6

您描述的是一个ServiceLocator。这被认为是现代应用程序设计中的反模式。本文介绍了原因。

  • @Colin您是否读过Mark Seemann声明ServiceLocator为反模式的理由?您仅获得了完全依赖注入的一些优点,但却错过了很多好处(即依赖的即时可见性)。此外,SL违反了各种软件设计规则,例如封装http://blog.ploeh.dk/2015/10/26/service-locator-violates-encapsulation/或SOLID http://blog.ploeh.dk/2014/05 / 15 / service-locator-violates-solid / (3认同)
  • @Colin您是否曾经遇到过这样的情况,即一个类为您提供了无参数的构造函数,然后又因为您不得不在一些看似无关的代码中初始化了六个“内部细节”而拒绝工作?没有?幸运的你。如果我每小时得到额外的报酬,我就不得不浪费时间查找和处理这样的“内部细节”,我可能会花半年时间休假。Trace类具有静态的侦听器集合。多数民众赞成在一个明显的依赖性,而不是一个“内部细节”。 (2认同)
  • @Colin,您是对的,隐藏类的内部细节很重要。问题在于,通过注入服务容器,您将隐藏该类的_external_详细信息。与方法和属性一样,类的依赖关系也是公共API的一部分。如果您需要提供X和Y才能使一个类起作用,那么您如何知道该类没有明确要求X和Y(例如,通过构造函数)?“当类在运行时崩溃时”不是这个问题的好答案。 (2认同)