【发布时间】:2011-09-26 13:17:53
【问题描述】:
我在 .NET 中使用 IoC(主要是 Unity)和依赖注入已经有一段时间了,我真的很喜欢这种模式,它可以鼓励创建松耦合的软件类,并且应该更容易隔离以进行测试.
我通常尝试坚持的方法是"Nikola's Five Laws of IoC" - 特别是不注入容器本身,只使用构造函数注入,以便您可以从其构造函数签名中清楚地看到类的所有依赖项。 Nikola 确实有一个帐户,但我不确定他是否仍然活跃。
无论如何,当我最终要么违反了其他法律之一,或者通常以某种感觉或看起来不正确的事情而告终时,我不得不质疑我是否遗漏了什么,可以做得更好,或者只是不应该在某些情况下不要使用 IoC。考虑到这一点,这里有几个例子,我将不胜感激任何指针或进一步讨论这些:
-
依赖项太多的类。 (“任何具有超过 3 个依赖项的类都应因违反 SRP 而受到质疑”)。我知道这个问题在依赖注入问题中出现了很多,但是在阅读了这些之后,我仍然没有任何 Eureka 时刻可以解决我的问题:
a) 在大型应用程序中,我总是发现我需要 3 个依赖项来访问基础设施(示例 - 日志记录、配置、持久性),然后才能获得类所需的特定依赖项(希望是单一职责) ) 任务完成。我知道将这些依赖组重构和包装成一个的方法,但我经常发现这只是其他几个服务的外观,而不是它自己的任何真正责任。如果认为该类仍具有单一职责,是否可以在此规则的上下文中忽略某些基础架构依赖项?
b) 重构可能会增加这个问题。考虑拆分一个已经变得有点大的类的相当常见的任务——您将一个功能区域移动到一个新类中,第一个类变得依赖于它。假设第一个类仍然需要它之前的所有依赖项,它现在有一个额外的依赖项。在这种情况下,我可能不介意这种依赖关系更紧密地耦合,但是让容器提供它仍然更整洁(与使用 new ...() 相反),即使没有新的依赖关系它也可以做到它自己的界面。
c) 在一个具体示例中,我有一个类负责每隔几分钟通过系统运行各种不同的功能。由于所有函数都属于不同的区域,因此这个类最终会产生许多依赖项,只是为了能够执行每个函数。我猜在这种情况下,应该考虑其他可能涉及事件的方法,但到目前为止我还没有尝试这样做,因为我想协调任务运行的顺序,并且在某些情况下应用涉及结果的逻辑路。
一旦我在应用程序中使用 IoC,似乎我创建的几乎每个由另一个类使用的类最终都会在容器中注册和/或被容器注入。这是预期的结果还是某些课程与 IoC 无关?仅在代码中添加新内容的替代方案看起来就像是代码气味,因为它紧耦合。这也与上面的 1b 有关。
我在应用程序启动时完成了所有容器初始化,为系统中的每个接口注册类型。有些是故意的单实例生命周期,而其他的每次解决时都可以是新实例。但是,由于后者是前者的依赖项,因此实际上它们也成为单个实例,因为它们只被解析一次 - 在单个实例的构建时。在许多情况下这无关紧要,但在某些情况下,我真的想要一个不同的实例,每次我做一个操作,所以我不能利用内置的容器功能,我不得不要么 i) 有而是使用工厂依赖项,以便我可以强制执行此行为,或者 ii)传入容器,以便每次都可以解决。这两种方法都在 Nikola 的指导下不受欢迎,但我认为 i) 是两害相权取其轻,我在某些情况下确实会使用它。
【问题讨论】:
-
请尝试一次只问一个问题。
-
拥有超过 3 个依赖项是很常见的。对我来说,超过 5 个依赖项就是代码异味。
-
是的,我现在意识到我应该把它分开,但由于背景都是相关的,我在写作时有点被带走了。把它归结为缺乏经验。现在无法重构我的问题,因为我有一些答案......
标签: c# .net design-patterns dependency-injection