Skip to main content

Design Patterns: The Inverse Extension Design Pattern

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

Comments

jjinux said…
Crazy, it took me a year and nine months to get that article published!
jjinux 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.

Popular posts from this blog

Ubuntu 20.04 on a 2015 15" MacBook Pro

I decided to give Ubuntu 20.04 a try on my 2015 15" MacBook Pro. I didn't actually install it; I just live booted from a USB thumb drive which was enough to try out everything I wanted. In summary, it's not perfect, and issues with my camera would prevent me from switching, but given the right hardware, I think it's a really viable option. The first thing I wanted to try was what would happen if I plugged in a non-HiDPI screen given that my laptop has a HiDPI screen. Without sub-pixel scaling, whatever scale rate I picked for one screen would apply to the other. However, once I turned on sub-pixel scaling, I was able to pick different scale rates for the internal and external displays. That looked ok. I tried plugging in and unplugging multiple times, and it didn't crash. I doubt it'd work with my Thunderbolt display at work, but it worked fine for my HDMI displays at home. I even plugged it into my TV, and it stuck to the 100% scaling I picked for the othe

ERNOS: Erlang Networked Operating System

I've been reading Dreaming in Code lately, and I really like it. If you're not a dreamer, you may safely skip the rest of this post ;) In Chapter 10, "Engineers and Artists", Alan Kay, John Backus, and Jaron Lanier really got me thinking. I've also been thinking a lot about Minix 3 , Erlang , and the original Lisp machine . The ideas are beginning to synthesize into something cohesive--more than just the sum of their parts. Now, I'm sure that many of these ideas have already been envisioned within Tunes.org , LLVM , Microsoft's Singularity project, or in some other place that I haven't managed to discover or fully read, but I'm going to blog them anyway. Rather than wax philosophical, let me just dump out some ideas: Start with Minix 3. It's a new microkernel, and it's meant for real use, unlike the original Minix. "This new OS is extremely small, with the part that runs in kernel mode under 4000 lines of executable code.&quo

Haskell or Erlang?

I've coded in both Erlang and Haskell. Erlang is practical, efficient, and useful. It's got a wonderful niche in the distributed world, and it has some real success stories such as CouchDB and jabber.org. Haskell is elegant and beautiful. It's been successful in various programming language competitions. I have some experience in both, but I'm thinking it's time to really commit to learning one of them on a professional level. They both have good books out now, and it's probably time I read one of those books cover to cover. My question is which? Back in 2000, Perl had established a real niche for systems administration, CGI, and text processing. The syntax wasn't exactly beautiful (unless you're into that sort of thing), but it was popular and mature. Python hadn't really become popular, nor did it really have a strong niche (at least as far as I could see). I went with Python because of its elegance, but since then, I've coded both p