Inversion of Control (aka IOC) is about breaking dependence between objects by placing interfaces between them. In particular, Inversion of Control focuses on breaking the dependence of high-level objects on their low-level modules.
Even more specificly, we talk here about dependency injection: When an object is created, it is given its dependencies, rather than making them on its own. (Another approach is ?ServiceDiscovery, not described here.)
Traditionally, an object creates the objects it needs. Something like:
1 class Eggs: 2 3 def __init__(self): 4 self.my_spam = Spam("foo", "bar") # Eggs is creating its own Spam.
However, we can invert the control. Instead of creating the object, and perhaps demanding that the environment conform to its choices, we invert control. The environment will fetch your dependencies for you.
1 class Eggs: 2 def __init__(self): 3 self.my_spam = None 4 5 def set_spam(self, spam): 6 self.my_spam = spam
(This variant of dependency injection is called setter injection.)
Ideally, we'd like a PEAK example here.
What did we gain by this? There is more control in the environment now. With the environment taking care of more details, there is less a chance that the object will include a hard-coded decision that the environment has to work around. The flip side is that the environment is now tasked with taking care of more details. But when you are working to create complex reusable components, this tends to be the direction of things: The fewer unnecessary decisions that the component makes, the more likely the component can be reused within another environment.
For a simple example of using peak.binding to do this, see PeakDatabaseApplications. ComposingHierarchies provides a more complex example.
For more about "Inversion of Control" aka "Dependency Inversion Principle," see:
"Inversion of control" was probably a bad name choice.
First, it's based on a rejection of a prior tradition. As the older tradition becomes less known, people aren't so sure of what's being inverted against. That is, the phrase is mortal.
Second, the relationship between high-level modules and low-level modules isn't necessarily inverted. Rather, there is now an "environment out there," and "me out here." Perhaps it would be better to think in terms of "inside, outside," or even "near, far," rather than "high, low." When dependencies are all held internally, there is a clear high-low relationship: Things that are held are low, things that hold you are high. But when all dependencies are external, there is no such clear high-low relationship. That thing that you thought was below you may now instead just be a facet of the thing that's "above" you. And vice versa. Or maybe not. The point is, you don't know.
?ExternalControl may have been a better name for the general principle behind "Inversion of Control."
-- ?LionKimbro 2005-04-17 06:04:09