我很好奇依赖倒置原则,以及是否应该一直严格执行。
我知道使用注入接口通常会促进松散耦合,这会产生积极影响。
但是,某些类型的类很可能总是只有一个实现,并且可能不会随着时间而改变。我真的在质疑让每个对象都由一个接口支持,例如 FooService,与 FooServiceImpl。
我处于两难境地,因为我认为具体的类注入通常被许多人所反对。
tl;dr
是否应该始终只使用接口进行依赖注入,即使某些类不太可能更改,因此,通过接口支持它似乎会增加不必要的复杂性?
我很好奇依赖倒置原则,以及是否应该一直严格执行。
我知道使用注入接口通常会促进松散耦合,这会产生积极影响。
但是,某些类型的类很可能总是只有一个实现,并且可能不会随着时间而改变。我真的在质疑让每个对象都由一个接口支持,例如 FooService,与 FooServiceImpl。
我处于两难境地,因为我认为具体的类注入通常被许多人所反对。
tl;dr
是否应该始终只使用接口进行依赖注入,即使某些类不太可能更改,因此,通过接口支持它似乎会增加不必要的复杂性?
只是几件事。
Dependency injection (DI)
!== Inversion of Control (IoC)
!==Dependency Inversion Principle (DIP)
除了这个,我想不起关于这个主题的更好的(同样简短和解释性的)阅读
第二个方面是依赖于语言和(或)工具。当然,我不能说所有可用的语言及其工具堆栈,但可能有一些地方测试加倍接口会比生成一个双倍作为被模拟类的子类更好的方法。
所以我个人(和主观)的答案
依赖注入是否应该始终只使用接口完成,即使某些类不太可能更改,因此,通过接口支持它似乎会增加不必要的复杂性?
绝对是“不”,因为类结构中不必要的复杂性。此外,做 DI 通常意味着使用某种依赖注入容器来管理依赖关系,这反过来又意味着额外的配置工作。
就个人而言,只有当我确实明确地有这样的意图时,我才会按意图引入接口。代码中出现的所有其他接口只是开发/重构过程中的提取(换句话说,我只在我或我的代码需要这些抽象时才创建这些抽象)。
你是对的,只要有多个实现,依赖注入就开始有用了。我知道您只有一个具体的实现,但是如果您遵循开发最佳实践,您将希望对每个类进行单元测试。如果 BarService 依赖于您的 FooService,您将编写一个单元测试 BarServiceTest,它依赖于 FooService 的假实现(模拟或类似的东西)。
换句话说,一旦您编写了对应用程序的单元测试,您最终就会得到服务的实现:运行时使用的真实的,用于单元测试的假的(或单个实现,但根据上下文配置不同) .