Wednesday, December 21, 2005

Design Patterns: The Inverse Extension Design Pattern

I wrote an article for Linux Journal called The Inverse Extension Design Pattern.

2 comments:

Shannon -jj Behrens said...

Crazy, it took me a year and nine months to get that article published!

Shannon -jj Behrens said...

> Thanks for your reply.

Thanks for your patience as I try to explain what I'm talking about.

> It gives me some idea of what you are getting at. However, on the basis of your reply I wouldn't be able to write down an example of the class of problems that Inverse Extension solves. I'm still puzzled as witnessed by the following questions.
>
> Does the Layout class encapsulate the common look and feel?

Yes, a Layout does encapsulate the common look and feel. By "common look and
feel", I mean that all of our apps look and behave pretty much the same. In my
code, I've used the term Layout pretty much as an interface.

> Do I understand you correctly that the hierarchy is as follows, :- indacting subcalssing, Layout :- Application :- Section :- Page?

Well let me step away from the hypothetical and talk about an actual class
hierarchy (top to bottom). Screens are the main content. Layouts are pretty
much any parent of a screen. I'll start with the layouts, and at the bottom
are the screens.

In Aquarium, which is my open source framework:

Bare -- This class understands content types, HTTP headers (including turning
on or off HTTP caching), etc.

Some subclasses in your app might include a screen that generates an XML
report or a screen that generates a dynamic image containing a graph.

HTML -- This is mostly for people who want to type the HEAD, HTML, BODY,
etc. tags themselves. It knows that it has content type text/html.

CssAndJavaScript -- This class knows about the basic layout of HTML. It has
methods for the title, CSS, JavaScript, etc. that can be overriden. It uses a
bunch of defaults that are defined in a properties file. It's here so that I
don't have to duplicate boilerplate.

Simple screens supclass from CssAndJavaScript when I'm trying to get a
message out without caring about look and feel. Consider the screens that
Apache uses for 404, etc.

Now, from within my common look and feel code, which is used by multiple apps
at my company:

Sparse -- This is the layout used for content where you don't want to show the
tabs.

The login screen, the help screens, the app-specific 404 screen, etc. all
extend from here.

Complete -- This layout contains the complete navigation, including tabs.

Most of the screens in the application extend from this. Most of apps
that use my common look and feel use this as their main layout.

Cluster -- This layout knows about extra navigation needed for clustering
(which we've unfortunately used as a misnomer for centralized management).

Only some of my apps need to worry about clustering. In those apps,
screens use this layout instead of the Complete layout.

Now, for actual screens:

various screens -- At the lowest level are the various screens. The basic idea
is that you start a screen by picking how much you want your parent class to do
for you automatically. You can always override methods defined in your parent
classes that it sets up for you to override, such as getTitle. You usually try
to pick the most specialized layout (e.g. Cluster or Complete depending on
whether or not your app supports clustering), however, certain screens need to
assert more control. For instance, it makes no sense for an XML report to
subclass the Cluster layout.

> Are Screens and Pages synonyms?

Yes, sorry about that. Screen is the actual "interface". I used page as a
synonym although there's nothing actually called page in my code.

> If not, where does Screen fit into this model?
>
> What is a Section ? I.e. what does it represent?

Now that I've laid out a concrete class hierarchy, let's just drop the
hypothetical stuff.

> How do these classes relate?

All those classes above extend from one another.

> What is the behaviour?

Based on inverse extend, each higher level class's __call__ method gets called.
Whenever it's ready, it passes off control to the child class's __call__
method. Hence, the parent classes "wrap" the child classes. This really makes
sense in HTML.

(It's also useful in a couple other contexts. Imagine a parent class that
checks access restrictions beforing allowing access to the child class. Note,
the parent class can prevent the child class's __call__ method from running at
all by simply refusing to call callNext! I have found this to be a useful
technique.)

> I.e. what methods are involved,

Everyone has a __call__ method (which is a Pythonism).

> what do they do and how do they call eachother?

Layouts look like (pseudocode):

class CssAndJavaScript(HTML):

def __call__(self, callNext):
# do stuff, like include the navigation
callNext(*args, **kargs) # Let the subclass do its stuff.
# do more stuff, like include the copyright footer

Screens look like (pseudocode):

class MyScreen(CssAndJavaScript):

def __call__(self):
# Do my main content

> What is its public interface?

In Aquarium, it's easy. Everyone has a __call__ method.

> What is its context?

I have the notion of a context, but I'm pretty sure it doesn't match what
you're asking about. The important thing is that the child class's __call__
method is called by the parent class's __call__ method in order to do its work
at just the right time.

> How does a client use an Layout instance? How is a page ulimatally displayed?

Well, Aquarium uses Cheetah for this. Here's a simple screen:

| #extend aquarium.layout.Cluster
| #implements __call__
|
| Hi! I'm a simple looking screen, but my parent automatically takes care of
| outputing all the common look and feel!

When you load a URL in the browser, Aquarium maps the URL to a particular
screen. Then it calls inverseExtend on that screen's __call__ method. Hence,
the parent class gets to do work, and then it passes control down the
inheritance hierarchy, until finally the screen gets to output its main
content.

> What do the doCommonLookAndFeel, doApp, doSection, doScreen do?

Dropping the hypothetical names.

> Return html?

Yes, actually they do. Hence, the parent class can take that HTML and do
whatever it wants with it.