Dont Call Me

Some libraries are easy to use: I instantiate their objects and make calls according to the needs of my program. If I need to, I can easily swap them out for another library: usually, they're used in a wrapper, so I just modify the wrapper.

Some are not as easy to use. They instantiate my objects and make calls to them on their own schedule. They ask that my objects inherit from their base classes. These sorts of libraries suffer from delusions of grandeur: they think that their vision is more important than my program. I have to suffer all kinds of contortions to make their grand vision fit the practical requirements of my situation. I can't just swap out the library for something else: its tentacles are inextricably wrapped around my objects. I don't like these kinds of libraries.

DontCallMe. I'll call you.

Any practical examples of say, a GUI framework that fits the DontCallMe requirement?

EJB - not GUI, but gooey.


Please call me.

I like these kinds of frameworks when they're written properly. They do most of the work and all I have to supply is a callback that does my special behavior. A good example are VMS AsynchronousSystemTraps. You ask the OS to perform some operation and tell it which method to call when it completes.


In reverse, called the HollywoodPrinciple. Don't call us - we'll call you.


The HollywoodPrinciple line was used by MacApp guru IanJoyner to help the jump from procedural to OO programming (back in 87). Ian's advice was to design routines to do as little as possible, returning control to the framework as soon as possible. Also advocated LotsOfShortMethods.

The moral seems to be, old code calling new code (the power of OO) makes it easier to write bad libraries.

Where do you see that moral?

One possible cure for this is using CallWithCurrentContinuation to set up coroutines (see ContinuationsAndCoroutines). Another way is WindowThreadControlThread.


I can't just swap out the library for something else: its tentacles are inextricably wrapped around my objects.

So write your own library that does your program's real work, and get the control-freak library to call a wrapper for your library.

That approach fails as soon as I want to use TWO control-freak libraries.

No it doesn't. Send each library it's own object. Inside that object interact gracefully with your other objects.

[Wrapping a framework is conceptually easy but is nontrivial to implement, so this could still be called a kludge. Also, often most of the hard part of a framework is in the API it offers, so once you've duplicated that in a wrapper, sometimes it's not that big of a deal to duplicate its implementation as well -- if there were a point. But there may not be, because the API itself may be insisting on the delusions of grandeur that make it a pain to use.]

Sorry, I don't understand. Why would you duplicate implementation? An example might help. All of the frameworks I've used that wanted to call my code provided small, clean interfaces for me to implement. One set of examples are J2EE authentication providers. They vary from app server to app server, but the ones I've worked with consist of a method that returns true if the user name and password are correct and some way to indicate group/role membership.
I think it probably depends. For example, the following is idiomatic Scala code:
    aCollection foreach {(elem) =>
      // do something with elem
      println(elem)
    }
For those not familiar with Scala, this would be a bit like doing something like this in Java:
    import scala.*;
    // ...
    aCollection.foreach(new Function1<ElemType?, Unit> {
       Unit apply(ElemType? elem) {
           println(elem);
           return Unit.instance()
       }
    });
Don't call us, indeed. This is idiomatic in Scala, so almost everything uses things like that. You do have to modify your element access to fit this type of iteration, and even then, it could decide to do it in random order, or not at all. (I'll ignore head and tail for a bit, because they don't technically have to be implemented by a Transversable collection.) Yes, it does think it knows better when to do whatever it is you want to do to each element than you. What of it?
    Iterator<ElemType?> iter = aCollection.getIterator();
    while(iter.hasNext()) {
        ElemType? elem = iter.next();
        println(elem);
    }
Or even (shudder):
    for(int i = 0; i < aCollection.getSize(); i++) {
        ElemType? elem = aCollection.get(i);
        println(elem);
    }
So, which is better? Iteration where you have control, or where the library does?

Please give me an example of where the HollywoodPrinciple could make things harder to maintain. And I want code, please. Even if it's in Ook! representing objects with an incredibly complex message-passing system.


See Also: DefinitionOfFramework, FrameworksConsideredHarmful

EditText of this page (last edited February 7, 2011) or FindPage with title or text search