Z3 ECM Enterprise Content Management for Zope3

The Zope3 presentation layer (adaptation revisited)


    Views in Zope3 are implemented as multi-adapters.

This is pretty much a summary of the Zope3 presentation stack, so let us dig into it.

History: Views as in M-V-C

First of all, the term View is borrowed from the Model-View-Controller design terminology (a.k.a MVC).

From http://www.enode.com/x/markup/tutorial/mvc.html:
Model-View-Controller (MVC) is a classic design pattern often used by applications that need the ability to maintain multiple views of the same data. The MVC pattern hinges on a clean separation of objects into one of three categories — models for maintaining data, views for displaying all or a portion of the data, and controllers for handling events that affect the model or view(s).

The pattern is 25 years old (cf Applications Programming in Smalltalk-80(TM): How to use Model-View-Controller).

Simplified MVC (the UI-delegate)

In Zope3 however, View and Controller are combined inside a same element called ... a view, this is a simplified model of MVC, as implemented in the Swing framework. In Swing however to avoid a confusion with the MVC term "View", this element is called the UI-delegate (see ).

The UI-delegate (i.e. the Zope3 view) manages both interaction and presentation, so that in the end we only have two elements:
  1. a model
  2. a view (UI-delegate)

In the case of a browser view for instance, the View (as in MVC) would correspond to the HTML and javascript code of a web page and the Controller (as in MVC) would be all the methods (Form POST, GET, and other RESTful URLs) associated to the View that allow user interaction with the page.

For instance when some form data gets posted to the "/folder/addItems" URL, the 'addItems' method will be called on the server.

Hence a Zope3 view needs to implement:

  • controller methods (e.g. 'addItems(...)')
  • the actually rendering of the view (this is done with the __call__() method). Usually the __call__ method delegates the rendering to the Page Template engine (ZPT), but it could as well be implemented as:
def __call__(self):
return "hello world."
The pattern is classic in web application frameworks since the view and the controller are usually tightly coupled. In an application server environment the Controller is usually tied to the publisher's REQUEST - RESPONSE lifecycle since user actions initiate a new request. Also at the end of the request, either the same page is refreshed or a new page is displayed after a redirection has occured. Hence the view (as in MVC) is very much tied to the response phase.

Why using multi-adapters?

A view in Zope3 is a multi-adapter. It adapts the contextual object (a.k.a the context) AND the request. The reason why an adapter is used is because the publisher needs to find a "suitable view" for the object depending on the type of request (HTTP, FTP, XMLRPC, ..), and this is done in Zope3 by looking up the view in the adapter registry based on the "context + request" signature.

In fact both the contextual object and the request implement interfaces, hence there is a unique type signature for each combination of object types (e.g. IFolder, ICalenderItem, ICatalog, ...) and request types (IHTTPRequest, IXMLRPCRequest, ... see zope.publisher.interfaces for the list of available request types).

Hence the Zope3 view has access to:

  • the contextual object (the model as one part of the adaptee)
  • the request (as the other part of the adaptee)
  • the session (bound to the request)
  • the application's context

This is pretty neat.

However it only solves the "lookup" part of the problem. Indeed this guarantees that the right view will be used in a given context.

Ian Bicking in its recent "Zope3 critique" article remarks that this it feels too much like a model-driven approach, and the presentation layer is not the one that drives the data.

In fact I recently asked myself this question, so let us see why this is really happening ...

"pull"-style vs. "push"-style MVC

It is clear that the question is:

  • is it the presentation layer that should pull the data that it needs or
  • is it the model that should push what data will be presented?
  • or both?

In one case we have a "model-driven" approach (push-style MVC) as in Zope3 (or I would say an object-driven approach).

In the other case we have a "template-driven" or "presentation-driven" approach (pull-style MVC).

Seam implements both, but mostly uses the "pull"-style approach. The reason is that you often don't know for sure what model(s) you will need to pull data from until the page has actually been displayed.

Basically Seam will see that the presentation needs a given component and it will pull it for you automatically and manage its entire lifecyle. So eventually a view may pull 5 or 10 different models.

In the case of Zope3 views however there is place for only one adapted object, so practically you have to choose one contextual object before you start creating the view and the template.

Often you end up with a view class that needs to pull data from other models. This is done by storing model keys in the request (session, cookies, ...) and the view implementation soon becomes spaghetti code, because it needs to manage session objects, cookies, request parameters and do component lookups.

Of course one may consider that this is a problem that exists with all object-oriented approaches (i.e. the view is derived from the object), and in fact if you look at Zope CMF you will see that the only really contextual object is the folder or the document that is being displayed.

However in reality the presentation stack must be able to accommodate many contextual objects and the adaptation from object to view does not allow that.

Comments

sort by threads Subject Author Date
  Collapse Well, sure, but... lregebro 10/10/06 18:05
    Collapse Re: Well, sure, but... Jean-Marc Orliaguet 10/10/06 18:37
      Collapse Re: Well, sure, but... optilude 10/10/06 20:10
        Collapse Re: Well, sure, but... Jean-Marc Orliaguet 10/10/06 22:51
          Collapse Re: Well, sure, but... optilude 11/10/06 01:00
            Re: Well, sure, but... optilude 11/10/06 01:02
            Collapse Re: Well, sure, but... Jean-Marc Orliaguet 11/10/06 09:38
              Re: Well, sure, but... optilude 11/10/06 09:46
Posted by Jean-Marc Orliaguet @ 10/10/2006 04:32 PM. - Categories: user interface, web design -  8 comments