4th*_*ace 32 methodology design-patterns dependency-injection inversion-of-control
我看到很多文章都说IoC和DI有多棒,而且没有关于它为什么不那么好的文章,因为它可以使代码更复杂.我还看到IoC不应该是代码的核心部分,而是更多的库和插件.文章通常只是一个小参考,这两个模式如何使代码更复杂,但在细节上没有多少.这是我的问题 - 具体应该在哪些地方使用这些模式?
这是一个很好的主题:什么是控制反转?.如果你向下看,有一篇关于拼写检查的帖子和另一篇关于IoC如果只是一个拼写检查器可能不是很好用的帖子.作为一般准则,如果不使用IoC,我只有一个具体的接口类?意思是,我有IMyClass.然后只有实现IMyClass的具体MyClassA.我为什么要在那里使用IoC?
如果我有MyClassA,MyClassB和MyClassC,每个都实现IMyClass,那些可能是IoC正确的候选者吗?
从同一个帖子,有谁知道这篇文章意味着什么:
Sam*_*ijo 32
关于只有一个接口实现的问题.使用IoC时,使用接口仍然很有用.使用模拟这些接口创建真正的单元测试(不依赖于接口实现正常工作)会容易得多.使用IoC的核心是使代码更容易测试.因此,如果您不想测试,请不要使用IoC,或者在没有测试的情况下已经有更好的测试计划.
恕我直言,DI和IoC的复杂性增加是通过更容易测试和更少耦合的代码来实现的.更容易隔离问题并进行未来的更改.您也可以更好地控制其行为.
我可以看到何时不使用IoC容器(因为它会导致配置开销).这可能发生在小项目上,您可以手动执行,而不是使用容器.但是,除非你不打算测试你的代码,否则我看不到使用DI会造成太多损失......
Ber*_*ard 21
控制倒置=婚姻
IOC容器=妻子
婚姻是一种已知模式的定义 - 妻子是该模式的实施;-)
伯纳德.
Nic*_*rdt 15
使用IoC容器不是决定在单个类的级别上进行 - 在任何项目中,您将拥有容器创建和不创建的类型.
复杂性权衡是这样的:
如果您曾经历过即使设计良好且维护良好的代码库变得难以管理的现象,您也遇到了IoC容器解决的问题.
Aus*_*nen 11
从城堡项目:
我为什么不用它?
如果您不熟悉这些概念并且没有意识到他们试图解决的问题,则不应使用Inversion of Control容器.
此外,根据项目的大小和复杂程度,IoC容器可能过度.更喜欢在大中型项目中使用它.
关于IoC的抱怨很容易理解:IoC将简单的东西变成了复杂的东西.假设你想对列表的每个元素做一些事情(伪代码):
for each i in list:
do_something(i)
Run Code Online (Sandbox Code Playgroud)
从本质上讲,IoC正在将循环迭代的责任转移给其他人.因此,我们最终会得到更像这样的东西:
ioc = new IocContainer()
ioc.register_callback(do_something)
ioc.go()
Run Code Online (Sandbox Code Playgroud)
请注意,即使在这种简单的形式中,代码也比原始代码长......并且不计算IocContainer的实现.
然后,以其最好的形式,IocContainer可以静态初始化或通过静态Main()函数或其他隐藏的地方进行初始化,并且register_callback()函数会根据迭代通过列出所有列出的XML文件的其他代码自动调用你的do_something()函数和(有时)甚至是迭代的列表内容.
是的,XML文件使您的软件更易于配置!对?您可以通过更改简单的文本文件来更改列表中的某些内容!
除此之外,具有讽刺意味的是,您的源代码现在更长,更难理解,它依赖于各种新的,可能是错误的库(包括IocContainer和XML解析器),并且您实际上更难以维护:XML代码是难比原来简单的源代码回路理解和编辑(不管是什么语言的循环写入).你也很少控制你想要进行迭代的方式(排序或未排序?深度优先或广度优先?),因为IocContainer正在承担你的责任.
对于像插件这样的东西,使用IoC是有意义的,因为主应用程序控制执行过程是合乎逻辑的,并且只是向插件寻求帮助.这被称为"提供挂钩",并且比IoC术语长得多.
对于像单元测试这样的东西(我经常看到它被抛出的地方),IoC通常被证明是无益的,因为你的测试需要能够模拟各种奇怪的情况,而IoC只是不断进入这样的方式.
IoC的基本假设是加载数据和循环通过某种程度上是困难的并且需要被删除; 这种假设不正确,因为它无论如何都不会超过几行(或者你可以将它移动到一个单独的函数),即使它确实保存了代码,也会降低你的灵活性.