Dependency injection 通过构造函数传递什么,通过接口传递什么?

Dependency injection 通过构造函数传递什么,通过接口传递什么?,dependency-injection,Dependency Injection,这是一个关于依赖注入的问题。在构造服务对象时,我们在构造阶段通过构造函数传入协作者。服务对象将实现一个接口,该接口将在运行阶段调用 有时很难知道某个特定对象是应该通过构造函数传递,还是应该是服务类实现的接口的一部分 关于选择一个选项而不是另一个选项,有什么规则吗?当您知道在编写代码的场景中只调用一次接口时,问题就变得最困难了。我经常使用的经验法则是,该类是否可以在不传入值的情况下运行,并与构造函数的复杂性相平衡。如果类在没有参数的情况下无法正常运行,则最好将其放入构造函数中。另一方面,如果类被设

这是一个关于依赖注入的问题。在构造服务对象时,我们在构造阶段通过构造函数传入协作者。服务对象将实现一个接口,该接口将在运行阶段调用

有时很难知道某个特定对象是应该通过构造函数传递,还是应该是服务类实现的接口的一部分


关于选择一个选项而不是另一个选项,有什么规则吗?当您知道在编写代码的场景中只调用一次接口时,问题就变得最困难了。

我经常使用的经验法则是,该类是否可以在不传入值的情况下运行,并与构造函数的复杂性相平衡。如果类在没有参数的情况下无法正常运行,则最好将其放入构造函数中。另一方面,如果类被设计用来做一些需要额外工作的事情,比如通过套接字接受连接,那么这些工作通常应该延迟到以后的函数

我喜欢这样想:

  • 构造函数参数是实现细节
    • 它们适用于所有操作
    • 它们不会因任何操作而改变(不变)
    • 没有它们,界面是可以理解的
    • 它们是反映应用程序的配置值
  • 方法参数是上下文的
    • 它们的作用域为单个操作
    • 它们是反映应用程序数据流的运行时值
很多艺术在于正确地构建问题。例如,我们可能会对自己说“我需要在用户表中创建一个新行”。从这个角度来看,这些签名中的任何一个都很好:

void Insert(User user);

void Insert(User user, IDbConnection dbConnection);
但是,我们可以分解任务定义:

意图:创建新用户

实现细节:用户是表中的一行

让我们将任务框架为“我需要创建一个用户”。这为我们提供了一种评估上述两个签名的方法,有利于符合我们意图的签名:

void Insert(User user);
对操作意图及其数据适用范围的分析通常会给出可靠的结果