关于只有一个接口实现的问题。当你使用IoC时,使用接口仍然很有用。使用这些接口的模拟来创建真正的单元测试(不依赖于接口实现是否正常工作)会更容易。使用 IoC 的核心是让代码更容易测试。因此,如果您不想测试,或者已经有了更好的测试计划而不使用 IoC,请不要使用 IoC。
恕我直言,DI 和 IoC 复杂性的增加是通过更容易测试和更少耦合的代码来实现的。更容易隔离问题并进行未来的更改。您也可以更好地控制它的行为。
我可以看到何时不使用 IoC 容器(因为它会导致配置开销)。这会发生在小型项目中,您可以手动完成,而不是使用容器。但我看不出使用 DI 有多大损失,除非你不打算测试你的代码......
About your question about having only one interface implementation. When you use IoC, it is still useful to use an interface. It will be much easier to create real unit tests (that doesn't depend on the interface implementation to be working correctly) using mocks for these interfaces. The core of using IoC is making code easier to test. So, don't use IoC if you don't want to test, or already have a better plan on testing without it.
IMHO, DI and IoC increase in complexity comes is paid by having an easier to test and less coupled code. It's easier to isolate the problems and to make future changes. You can control its behavior better too.
I can see when not to use an IoC container (as it results in configuration overhead). This would happen on small projects, where you can do it manually, instead of using a container. But I can't see much loss from using DI, unless you're not planning to test your code...
是否使用 IoC 容器并不是在单个类级别上做出的决定 - 在任何项目中,您都会拥有由容器创建和不是由容器创建的类型。
复杂性权衡是这样的:
对于少量组件,IoC 容器确实会增加一些开销。
随着应用程序中组件数量的增加:
如果没有 IoC 容器,添加新组件或重构往往会变得越来越困难
使用 IoC 容器,添加新组件或重构保持不变:您只需担心要添加或更改的组件的直接依赖关系。
如果您曾经经历过这样的现象:即使是精心设计和维护的代码库也会因大小而变得难以管理,那么您就遇到了 IoC 容器解决的问题。
Using an IoC container or not isn't a decision to make at the level of individual classes - in any project you'll have types that are and aren't created by the container.
The complexity tradeoff is this:
For a small number of components, an IoC container does add some overhead
As the number of components in an application increases:
Without an IoC container, adding new components or refactoring tends to get increasingly difficult
With an IoC container, adding new components or refactoring stays the same: you only ever need to worry about the immediate dependencies of the component you're adding or changing.
If you've ever experienced the phenomenon of even a well-designed and maintained codebase becoming unmanageable with size, you've experienced the problem that IoC containers solve.
You should not use an Inversion of
Control container if you are not
familiar with the concepts and if you
do not realize the problems they try
to solve.
Also, depending on the size and
complexity of the project, an IoC
container might be overkill. Prefer to
use it on medium to large projects.
具有讽刺意味的是,您的源代码现在更长并且更难理解,它依赖于各种新的、可能有缺陷的库(包括 IocContainer 和 XML 解析器),并且您实际上已经制作了更难维护:XML 代码比原始的简单源代码循环更难理解和编辑(无论循环是用什么语言编写的)。您对如何进行迭代(排序或未排序?深度优先还是广度优先?)的控制也较少,因为 IocContainer 正在剥夺您的责任。
对于插件之类的东西,使用 IoC 是有意义的,因为主应用程序控制执行过程并且只是到处向插件寻求帮助是合乎逻辑的。这称为“提供钩子”,其存在时间比 IoC 术语要长得多。
对于单元测试(我经常看到它被扔掉的地方)之类的事情,IoC 通常被证明是没有帮助的,因为你的测试需要能够模拟各种奇怪的情况,而 IoC 只是不断地陷入困境这样的方式。
IoC 的基本假设是加载数据和循环在某种程度上是困难的,需要被抽象出来;这个假设是不正确的,因为无论如何它永远不会超过几行(或者您可以将它移动到一个单独的函数),即使它确实节省了代码,它也会降低您的灵活性。
The complaints about IoC are easy to understand: IoC turns something simple into something complicated. Let's say you wanted to do something to each element of a list (in pseudocode):
for each i in list:
do_something(i)
IoC, essentially, is moving the responsibility for loop iteration to someone else. Thus, we end up with something more like this:
ioc = new IocContainer()
ioc.register_callback(do_something)
ioc.go()
Notice that even in this simple form, the code is longer than the original... and that's not counting the implementation of IocContainer.
Then, in its fanciest form, the IocContainer can get initialized statically or by a static Main() function or somewhere else hidden away, and the register_callback() functions get called automatically based on some other code that iterates through an XML file that lists all your do_something() functions and (sometimes) even the contents of the lists to iterate through.
Yay, the XML file has made your software more configurable! Right? You can change which somethings are done to your list just by changing a simple text file!
Except, ironically, your source code is now longer and harder to understand, it depends on all sorts of new, possibly buggy, libraries (including the IocContainer and an XML parser), and you've actually made it harder to maintain: XML code is harder to understand and edit than the original simple source code loop (no matter what language the loop is written in). You also have less control over exactly how you want to do the iterating (sorted or unsorted? depth-first or breadth-first?) since IocContainer is taking that responsibility away from you.
For things like plugins, it can make sense to use IoC, since it's logical for the main application to be in control of the execution process, and to just ask the plugin for help here and there. This is called "providing hooks" and has been around much longer than the IoC terminology.
For things like unit tests (which is where I've usually seen it thrown around), IoC usually turns out to be unhelpful, because your tests need to be able to simulate a wide variety of odd situations, and IoC just constantly gets in the way of this.
The fundamental assumption of IoC is that loading data and looping through is somehow difficult and needs to be abtracted away; this assumption just isn't true, because it was never more than a couple of lines anyway (or you could move it to a separate function), and even if it did save code, it reduces your flexibility.
为了回答您的具体问题,如果您有足够少的类可以手动合理地构造对象图,并且您不会多次重复相同的对象图实例化,那么您可能不需要 IoC 容器。
IoC/DI are not technologies, they are paradigms. Your question is akin to asking "When should I not use object-oriented programming?" It is a decision that is bigger than the individual units of your codebase.
To answer your specific question, if you have few enough classes where you can reasonably construct object graphs by hand, and you are not repeating the same object graph instantiations multiple times, you might not need an IoC container.
I guess I'd say the simple answer only use IoC on objects you wish to unit test.
If this seems flippant I'm sorry, it's out of frustration at code written with literally NO consideration given to unit testing. I don't really understand why there is added complexity--if I needed to know the actual object type for sure I can always print out the class at runtime.
This article addresses your question "where specifically should you not use these patterns?" and gives detailed examples regarding your comment that "the two patterns ([IoC and DI]) can make code more complicated":
You should not use IoC/DI where encapsulation is important.
You should not use IoC/DI where you cannot demonstrate concrete examples of how the complexity added through the use of IoC/DI is out weighed by the benefits of using IoC/DI.
发布评论
评论(8)
关于只有一个接口实现的问题。当你使用IoC时,使用接口仍然很有用。使用这些接口的模拟来创建真正的单元测试(不依赖于接口实现是否正常工作)会更容易。使用 IoC 的核心是让代码更容易测试。因此,如果您不想测试,或者已经有了更好的测试计划而不使用 IoC,请不要使用 IoC。
恕我直言,DI 和 IoC 复杂性的增加是通过更容易测试和更少耦合的代码来实现的。更容易隔离问题并进行未来的更改。您也可以更好地控制它的行为。
我可以看到何时不使用 IoC 容器(因为它会导致配置开销)。这会发生在小型项目中,您可以手动完成,而不是使用容器。但我看不出使用 DI 有多大损失,除非你不打算测试你的代码......
About your question about having only one interface implementation. When you use IoC, it is still useful to use an interface. It will be much easier to create real unit tests (that doesn't depend on the interface implementation to be working correctly) using mocks for these interfaces. The core of using IoC is making code easier to test. So, don't use IoC if you don't want to test, or already have a better plan on testing without it.
IMHO, DI and IoC increase in complexity comes is paid by having an easier to test and less coupled code. It's easier to isolate the problems and to make future changes. You can control its behavior better too.
I can see when not to use an IoC container (as it results in configuration overhead). This would happen on small projects, where you can do it manually, instead of using a container. But I can't see much loss from using DI, unless you're not planning to test your code...
控制反转 = 婚姻
IOC 容器 = 妻子
婚姻是已知模式的定义 - 妻子是该模式的实现;-)
Bernard。
Inversion of Control = Marriage
IOC Container = Wife
Marriage is the definition of a known pattern - Wife is the implementation of that pattern ;-)
Bernard.
是否使用 IoC 容器并不是在单个类级别上做出的决定 - 在任何项目中,您都会拥有由容器创建和不是由容器创建的类型。
复杂性权衡是这样的:
如果您曾经经历过这样的现象:即使是精心设计和维护的代码库也会因大小而变得难以管理,那么您就遇到了 IoC 容器解决的问题。
Using an IoC container or not isn't a decision to make at the level of individual classes - in any project you'll have types that are and aren't created by the container.
The complexity tradeoff is this:
If you've ever experienced the phenomenon of even a well-designed and maintained codebase becoming unmanageable with size, you've experienced the problem that IoC containers solve.
来自城堡项目:
From the Castle Project:
对 IoC 的抱怨很容易理解:IoC 将简单的事情变得复杂。假设您想对列表中的每个元素执行某些操作(以伪代码形式):
IoC 本质上是将循环迭代的责任转移给其他人。因此,我们最终得到的结果更像是这样的:
请注意,即使在这种简单的形式中,代码也比原始代码长......并且这还不包括 IocContainer 的实现。
然后,以其最奇特的形式,IocContainer 可以静态初始化,或者通过静态 Main() 函数或其他隐藏的地方进行初始化,并且基于一些其他代码自动调用 register_callback() 函数,这些代码循环访问列出了所有内容的 XML 文件。你的 do_something() 函数和(有时)甚至是要迭代的列表的内容。
是的,XML 文件使您的软件更加可配置!正确的?您只需更改一个简单的文本文件即可更改对列表执行的操作!
具有讽刺意味的是,您的源代码现在更长并且更难理解,它依赖于各种新的、可能有缺陷的库(包括 IocContainer 和 XML 解析器),并且您实际上已经制作了更难维护:XML 代码比原始的简单源代码循环更难理解和编辑(无论循环是用什么语言编写的)。您对如何进行迭代(排序或未排序?深度优先还是广度优先?)的控制也较少,因为 IocContainer 正在剥夺您的责任。
对于插件之类的东西,使用 IoC 是有意义的,因为主应用程序控制执行过程并且只是到处向插件寻求帮助是合乎逻辑的。这称为“提供钩子”,其存在时间比 IoC 术语要长得多。
对于单元测试(我经常看到它被扔掉的地方)之类的事情,IoC 通常被证明是没有帮助的,因为你的测试需要能够模拟各种奇怪的情况,而 IoC 只是不断地陷入困境这样的方式。
IoC 的基本假设是加载数据和循环在某种程度上是困难的,需要被抽象出来;这个假设是不正确的,因为无论如何它永远不会超过几行(或者您可以将它移动到一个单独的函数),即使它确实节省了代码,它也会降低您的灵活性。
The complaints about IoC are easy to understand: IoC turns something simple into something complicated. Let's say you wanted to do something to each element of a list (in pseudocode):
IoC, essentially, is moving the responsibility for loop iteration to someone else. Thus, we end up with something more like this:
Notice that even in this simple form, the code is longer than the original... and that's not counting the implementation of IocContainer.
Then, in its fanciest form, the IocContainer can get initialized statically or by a static Main() function or somewhere else hidden away, and the register_callback() functions get called automatically based on some other code that iterates through an XML file that lists all your do_something() functions and (sometimes) even the contents of the lists to iterate through.
Yay, the XML file has made your software more configurable! Right? You can change which somethings are done to your list just by changing a simple text file!
Except, ironically, your source code is now longer and harder to understand, it depends on all sorts of new, possibly buggy, libraries (including the IocContainer and an XML parser), and you've actually made it harder to maintain: XML code is harder to understand and edit than the original simple source code loop (no matter what language the loop is written in). You also have less control over exactly how you want to do the iterating (sorted or unsorted? depth-first or breadth-first?) since IocContainer is taking that responsibility away from you.
For things like plugins, it can make sense to use IoC, since it's logical for the main application to be in control of the execution process, and to just ask the plugin for help here and there. This is called "providing hooks" and has been around much longer than the IoC terminology.
For things like unit tests (which is where I've usually seen it thrown around), IoC usually turns out to be unhelpful, because your tests need to be able to simulate a wide variety of odd situations, and IoC just constantly gets in the way of this.
The fundamental assumption of IoC is that loading data and looping through is somehow difficult and needs to be abtracted away; this assumption just isn't true, because it was never more than a couple of lines anyway (or you could move it to a separate function), and even if it did save code, it reduces your flexibility.
IoC/DI 不是技术,而是范例。你的问题类似于问“我什么时候不应该使用面向对象编程?”这是一个比代码库的各个单元更大的决定。
为了回答您的具体问题,如果您有足够少的类可以手动合理地构造对象图,并且您不会多次重复相同的对象图实例化,那么您可能不需要 IoC 容器。
IoC/DI are not technologies, they are paradigms. Your question is akin to asking "When should I not use object-oriented programming?" It is a decision that is bigger than the individual units of your codebase.
To answer your specific question, if you have few enough classes where you can reasonably construct object graphs by hand, and you are not repeating the same object graph instantiations multiple times, you might not need an IoC container.
我想我会说简单的答案仅在您希望进行单元测试的对象上使用 IoC。
如果这看起来很轻率,我很抱歉,这是因为编写的代码实际上没有考虑单元测试。我真的不明白为什么会增加复杂性——如果我需要确定实际的对象类型,我总是可以在运行时打印出该类。
I guess I'd say the simple answer only use IoC on objects you wish to unit test.
If this seems flippant I'm sorry, it's out of frustration at code written with literally NO consideration given to unit testing. I don't really understand why there is added complexity--if I needed to know the actual object type for sure I can always print out the class at runtime.
本文解决了您的问题“具体在哪里不应该使用这些模式?”并给出了关于您的评论的详细示例,即“两种模式([IoC 和 DI])可以使代码更加复杂”:
http://java.dzone.com/articles/beyond-injection-concerns-ioc。
总结本文的两点:
This article addresses your question "where specifically should you not use these patterns?" and gives detailed examples regarding your comment that "the two patterns ([IoC and DI]) can make code more complicated":
http://java.dzone.com/articles/beyond-injection-concerns-ioc.
To summarize two of the points of this article: