- "Don't call us, we'll call you"
Relevant when you are writing a class/component that must fit into the constraints of an existing framework. You implement the interfaces, you get registered. You get called when the time is right.
This requires a distinctly different way of thinking from that which is taught in
introductory programming where the student dictates the flow of control.
is often called InversionOfControl
, or DependencyInjection
. You can think of it as a special case of TellDontAsk
, involving the creation and connection between classes.
I remember the first time I encountered this idea. I was developing a Windows application using Borland's OWL-framework (early '90s) and it took me a while to get used to the HollywoodPrinciple. It was kind of liberating though as it allowed me to concentrate on the business specifics of the application and not all the (Windows-specific) plumbing.
This is also relevant whenever you are writing an piece of code which you want to make modular and highly reusable. InversionOfControl is often used on the server side, to ensure independence from set-up and environment conditions. For instance, instead of declaring the Logger class inside the module, InversionOfControl would advise you to provide a setLogger() method that would allow the client application to set the logger to whatever it deems appropriate.
Richard E. Sweet, "The Mesa Programming Environment", SigPLAN Notices 20(7):216-229, July 1985. In the section "Design Goals":
- Don't call us, we'll call you (Hollywood's Law) A tool should arrange for Tajo to notify it when the user wishes to communicate some event to the tool, rather than adopt an "ask the user for a command and execute it" model.
is where an object's (or component's) initial condition and ongoing lifecycle is handled by its environment rather than by the object itself. Thus if a Foo
uses a BarHandler
, the appropriate instance of the BarHandler
will be provided by a container rather than obtained by the object. This allows cool patterns like InteractionOverState?
to naturally emerge as well as creating an environment that encourages MockObject
is doing some cool pattern-based thinking around this, but he won't let me paste a URL yet. This smells like what J2EE was originally trying to do before it got hijacked by resume-obsessed architects. Hopefully, it still can. Take a look at the the Nano and PicoContainer
s at http://www.picocontainer.org
for some very simple and very powerful fun. -- DanNorth
is what distinguishes a SoftwareFramework
from a "library". When using a framework, the application-specific code written by the programmer gets called by the framework.
uses this concept heavily in its Nucleus framework. Pretty much everything in Dynamo is a component which is accessed through the framework. -- WillSargent
It is not the same as EventDrivenProgramming
Can someone explain how the two ideas are different?
There are a lot of situations where you're not receiving events, but you're still getting phone calls.
Suppose object A traditionally create a B. Ah, but now, we've got an DependencyInjection
. Object B is going to be provided to object A, so that object A code doesn't have to depend on a particular B.
So, the environment that "hosts" A- it's going to give a B to it.
This is the HollywoodPrinciple
. But this is not an event.
By "event," people are referring to forms filled out when something happened "just in case" someone else might want to know about it.
This, in contrast, was a pre-planned operation. The code knew
that it was going to be talking with A, it knew
it was configuring A, it knew
it was building a B for A. The HollywoodPrinciple
was in effect, but this is not what we usually call an "event."
How about a real-world scenario.
Can someone explain what the win is for this? What does spring or
pico do with this pattern? What services can a container do based
on this feature? It seems to add a lot of obscurity to me because
there is now a magic layer and configuration files for hooking all this
up together. It's much clearer for an object to resolve its own references.
Basically, it makes the object more reusable. You can put the object through more scenarios, because it's customizable from the outside, rather than within the code. That is, you don't have to change the code for the object, in order to customize its use.
This is not to say this method should always be used. You are right: direct instantiation can be simpler, and even just as flexible, should it be easy for people to find the code to change, and should they have the ability to change the code.
Another explanation: When an object "resolves its own references" (as stated above) to concrete classes it forces the code to depend on specific implementations. Spring makes it easy to get rid of those concrete dependencies. You can write code that only depends on interfaces. The decision about which implementation of any interface will be used is pulled out of the code and placed in a configuration file (or database, or whatever). Even the way the configuration is stored can be abstracted out of code into data, so the code just knows that something will provide the configuration without depending on a specific implementation. That's very useful.
That's a configuration-based plug-in solution. The part to focus on here is that the model you're creating is going to be used by an object that you're not creating, via an interface that you didn't create either. Thus your model becomes the plug-in; i.e., InversionOfControl
Funny that this kind of programming has become a full theory. Since the 90s that I program in C++, the vast majority of the code was designed with pure virtual classes, i.e. interfaces, implementing InversionOfControl
, especially in the server side where, at the end of the day, you're called back by the middleware, so you're in a framework wether you want it or not. This way of programming enables a lot of possibilities and not only the ContainerKnowsAll?
kind of pattern.
The advantage seems to me the capability of having MockObject
s more easily and so to be able to unit test parts of the code, whereas sometimes, the transaction framework we can use is quite hard to configure for this purpose. But, even if some factories can be parameterized with configuration files (especially in Java, even if it can be done also in C++ with auto-record of implementations in the appropriate handler), the container can become quite quickly a GodClass
with a lot of design dependencies... on interfaces rather than on implementations. -- OlivierRey
for the opposite perspective.
See also BoyThisStuffMakesMeFeelStupid
See also http://wiki.opensymphony.com/space/XWork+Components
for an interesting use of DependencyInjection
to see how CallWithCurrentContinuation
can cause (or conceal) an DependencyInjection
without making it necessary to rewrite any code.
The Hollywood Principle: Like HOFs, but without the F.