使用 IOC 容器会降低应用程序的速度,因为它们中的大多数都在后台使用反射。它们还可以使您的代码更难理解(?)。光明的一面; 它们帮助您创建更松散耦合的应用程序并使单元测试更容易。使用/不使用 IOC 容器还有其他优点和缺点吗?
7 回答
如果您以简单的方式使用 IOC 容器,则反射仅在启动时使用 - 应用程序已连接以启动,然后它正常运行而无需容器的任何干预。当然,如果您在开始运行后使用 IOC 来解决依赖关系,那可能会略有不同 - 尽管我仍然希望它能够延迟解析并缓存,除非您已将其配置为每个都创建新实例时间。
至于让代码更难理解——恰恰相反!明确说明依赖关系后,更容易理解每个组件,并且配置文件清楚地表明了整个应用程序是如何连接在一起的。
好吧,我想我经历过的一个骗局是一些开发人员似乎无法掌握 IoC。我们有一些人无缘无故地反对它,除了他们不理解它们。(并不是说这是反对某事的坏理由,一点也不。)
它确实增加了一些抽象,似乎总是设法使某人或其他人感到困惑,但我想说在大多数情况下,利远大于弊。
我认为公平地说,如果您对如何使用 IOC 有专业的了解并且倾向于编写好的代码,那么 IOC 将使您的代码在除最小系统之外的所有系统上更易于理解。
但是,如果您在大多数类/方法都非常大并且重构的概念尚未掌握的地方工作,那么尝试使用 IOC 可能只会使软件更难理解。国际奥委会还必须被所有参与该项目的人所借鉴,因此这可能是一个考虑因素。
我认为国际奥委会是锦上添花;我喜欢糖霜,但只在一个漂亮的蛋糕上。如果蛋糕一开始不好吃,先把蛋糕整理好。
至于使用 IOC 的性能开销,在大多数情况下我不认为这是一个问题。开销不需要很大,并且考虑到当今 CPU 的速度,大多数人的运行时间很可能是数据访问。如果 IOC 被证明对于给定的代码位变慢,我会考虑添加一些返回对象的缓存,或者仅从那段代码中删除IOC。
我相信关于降低执行速度的假设与“C 比 C#/Java 更快”的论点大致相同。虽然这种说法对于特定的操作和/或结构简单的任务可能是正确的,但在复杂性上升的时候情况并非如此。
DI 框架让您专注于对象创建和依赖关系的方式可以在代码大小增加时创建更高效的系统。对于大型应用程序,我几乎可以肯定基于 DI 框架的代码将胜过任何替代解决方案。运行时的冗余太少了,很难提高效率!大多数额外开销也只是在第一次加载时。
高级 DI 容器还可以让您实现“范围”魔术,这是您在没有容器的情况下只能梦想的。使用范围代理,spring可以执行以下操作:
A Singleton
|
B Singleton
|
C Prototype (per-invocation)
|
D Singleton
|
E Session scope (web app)
|
F Singleton
实际上,您可以拥有十层单例对象,并且突然之间出现了一些会话范围。
可以以与其他方式完全不同的方式注入安全性之类的东西。通常有一个经典的悖论:GUI 层通常需要对安全权限有复杂的了解。服务层通常也需要这个,但通常在不同的细节级别(通常不如 gui 详细)。经典的方法是将其作为参数发送,将其放在线程本地或询问服务。使用弹簧,您可以将其直接注入您需要的地方,而其他人不需要知道。
这实际上改变了整个应用程序开发。我真的很难适应这一点,但在经历了这种痛苦之后,我发现它确实更接近于事情应该如何(而不是我们学会如何去做)。
所以我认为 DI 框架有可能改变你制作程序的方式,其影响远不止 DI。这不仅仅是调用new的一种美化方式。
我同意到目前为止的所有答案。
我想补充的是,它会产生一些开销,因此它并不真正适合小型应用程序。
中型和大型应用程序从使用 IoC 中获益最多。
您还可以查看这个问题以获取有关利弊的更多信息:温莎城堡有什么缺点吗?
在大多数情况下,您甚至不会注意到性能损失,因为对于“单例”对象,所有初始化只执行一次。我还认为 IoC 使理解代码变得不同:相反,IoC 风格的开发迫使您创建小的连贯类,而这些类反过来更容易理解。
如果您正在编写业务应用程序,则使用控制反转和依赖注入容器(结合其他敏捷实践和工具)将帮助您提高生产力和可靠性。
此外,您的应用程序可能会花费其大部分 CPU 时间来等待资源或等待人机交互,而没有做任何有用的事情。您的应用程序应该有足够的能力来进行几微秒的反射。