这更多是术语(技术写作),而不是纯粹的技术问题。我正在尝试围绕我们的应用程序中扩展依赖项注入编写一个重构建议(并将其分配给我自己)。虽然我们确实使用Spring来自动装配Bean,但是仍然存在使用实例化Bean的实例,这些实例MyClass obj = new MyClass(...)
可以完全注入。我想使我的建议使用优雅的命名法,并用适当的术语指代DI的设计模式。
“紧密耦合”是否足以作为DI的反义词?
这更多是术语(技术写作),而不是纯粹的技术问题。我正在尝试围绕我们的应用程序中扩展依赖项注入编写一个重构建议(并将其分配给我自己)。虽然我们确实使用Spring来自动装配Bean,但是仍然存在使用实例化Bean的实例,这些实例MyClass obj = new MyClass(...)
可以完全注入。我想使我的建议使用优雅的命名法,并用适当的术语指代DI的设计模式。
“紧密耦合”是否足以作为DI的反义词?
Answers:
不能。紧密耦合远不止依赖注入处理。
依赖注入将实现的决定外部化。这对解耦有很长的路要走,但是耦合不仅限于此。
依赖注入的一个很好的反义词是对依赖进行硬编码。当在一个行为对象内构造(使用新的或直接使用某些工厂)时,您已经将两个不同的关注点混淆在一起。服务定位器有助于解耦,但让您与服务定位器本身耦合。
耦合不仅仅是将构造和行为分开。如果我有101种必须按某种特定顺序从A类到B类调用的方法,则我紧密联系在一起。无关紧要的构造和行为是多么完美的分离。
耦合是两个对象相互依存的量度。任何导致难以在不影响另一个的情况下进行更改的因素都将导致耦合。依赖注入可以帮助实现这一点,但这还不是全部。
N
数小时...或直到选择答案为止。我知道当一个答案已经有10票而其他5个答案都没有时,我并不完全客观!
严格地说,依赖注入只有真正反对不依赖注入 -因此,任何依赖管理策略,是不依赖注入。
[不需要]耦合,尽管不完全是正交的问题,但可以通过两种方式发生或缓解。这些都与DependencyClass
:
public DependencyInjectedConstructor(DependencyClass dep) {
dep.do();
}
public DependencyLookupConstructor() {
var dep = new DependencyClass();
dep.do();
}
DependencyLookupConstructor
DependencyClass
在这种情况下耦合到特定对象。但是,它们都耦合到DependencyClass
。真正的弊端(如果这里有一个)不一定是耦合,DependencyLookupConstructor
如果DependencyClass
突然需要注入自己的依赖项,那就需要改变1。
但是,此构造函数/类的耦合更为松散:
public DependencyLocatingConstructor() {
var dep = ServiceLocator.GetMyDoer();
dep.do();
}
如果您使用的是C#,上面的代码将允许您在被调用时ServiceLocator
返回任何内容GetMyDoer()
,只要它具有do()
所DependencyLocatingConstructor
拥有的一切即可do()
。您可以获得编译时签名验证的好处,而无需耦合到完整的接口2。
所以,选择你的毒药。
但基本上,如果有一个特定的“依赖关系注入”对立面,那么“依赖关系管理策略”将是另外一回事。除其他外,如果您在对话中使用以下任何内容,我会认为它不是“依赖注入”:
具有讽刺意味的是,DI在较高级别上解决的一些问题是由于在较低级别上过度使用DI造成的。我一直很乐意在所有不必要的复杂性上工作,从而适应了不必要的复杂性,因为这些地方实际上帮助了很多地方……我承认,不良的表现使我产生了偏见。
2.使用服务位置还可以使您轻松地通过调用代码中的功能角色来指定相同类型的不同依赖项,同时仍然很大程度上不了解依赖项的构建方式。假设您需要解决User
或IUser
出于不同的目的:例如,Locator.GetAdministrator()
对比Locator.GetAuthor()
-或其他。我的代码可以在不知道其支持什么接口的情况下询问其功能需求。
DependencyInjectedConstructor(DependencyClass dep)
是DependencyClass可能是一个接口或抽象类。这就是为什么让C#编码人员使用接口前缀(如中)令我感到悲伤的原因IDependency
。作为客户,依赖项实际上不是我的事。只要不构建它,我所需要知道的就是如何与它交谈。这是别人的问题。
DependencyClass
是抽象接口。它仅要求构造/配置/位置逻辑存在于“其他地方”。...好吧,更重要的是,这个问题的关键在于,DI并非“紧密耦合的反面” :)
dynamic
参数。(但是var
,如果有内存,则不是参数。)因此,对于C#中的DI,我想我要么必须针对接口进行编码,要么就不得不完全放弃编译时验证。
dynamic
或var
从定位器获取对象,让我们忽略该接口,并使用可以满足do()
需要的任何类,无论该类是否实现了某些IDoer
接口。换句话说,如果我们有A-> B <-C,DI将A从C解耦,但是它要求A和C都耦合到B,并且即使D会阻止D的使用do()
。