Z3 ECM Enterprise Content Management for Zope3

The Zope Component Architecture: To a hammer, everything looks like a nail.

I have experienced issues with the Zope Component Architecture. This is the first part of a series.

Complexity

The feeling of complexity comes from the fact that some few very abstract concepts such as interfaces, adapters, and utilities are used all over the place to represent all sorts of more familiar concepts.

The Zope3 code leaves the programmer in the situation of a researcher attempting to decode a DNA sequence, i.e. when one is looking too close it is difficult to see.

An example

To find a book by its name, intuitively one would write something like:

>>> from my.app import registries
>>> print registries.getBookRegistry().getBookByName("The book on Zope")

once the 'registries' have been imported, the code completion comes for free (CTRL+space when using an IDE like Eclipse):

  - registries => getCarRegistry() => getListOfCars() ...
  
  - registries => getTypeManager() => getTypeByName() ...

... which means that the API is made available by simply typing the words in English.

One expresses the same idea in Zope3 as:

>>> from my.app.interfaces import IBook
>>> print queryUtility(IBook, name="Book on Zope")

... which amounts to the same quantity of code, but with reduced understandability because that begs the question:

  • what is an interface?
  • what is a utility?
  • what does queryUtility() actually return?

(in fact it returns a book, not a utility)

This forces the brain to handle two foreign concepts (interface, utility) in the place of two otherwise familiar concepts (book registry, book)

Of course there is no such equivalent 'code completion' feature possible in Zope3 since utilities are registered at runtime (in ZCML).

Also to find books one needs to know that they implement the IBook interface and that they are registered as utilities under a name.

Another example

To get the type of the book, one would write in English:

>>> book = Book(type=PAPERBACK)
>>> print book.getType()

but in the spirit of the Component Architecture one would use "interface types", instead:

first by registering book types:

>>> class IBookType(IInterface):
>>>     """The book type""

>>> class Book(object):
>>>     implements(IPaperBack)
>>> alsoProvides(IPaperBack, IBookType)

or even in ZCML:

  <interface interface="IPaperBack" type="IBookType" />

and then by querying the interface type on the book instance:

>>> book = Book()
>>> print queryType(book, IBookType)

It always take me a few minutes to figure out what is actually happening, hence I am not 100% sure that the code is right this time.

more and more complexity

It should also be noted that the recent refactoring of ZCML directives which aimed at removing "redundant" directives because they could be expressed in "simpler" terms as adapters or utilities does not really simplify the task.

Now a factory is a utility providing zope.component.interfaces.IFactory.

We are getting closer and closer to a complete ternary representation (interface, adapter, utility) of the world, which I am sure is an elegant concept, but for the abstract thinker only.

Conclusion: To a hammer, everything looks like a nail.

Comments

sort by threads Subject Author Date
  Collapse And now in the series, Rants while I slow back away out the door.... optilude 29/09/06 13:10
    Collapse Re: And now in the series, Rants while I slow back away out the door.... AlexGarel 04/10/06 11:38
      Re: And now in the series, Rants while I slow back away out the door.... optilude 05/10/06 17:18
  Collapse Unbalanced Comparison? Duncan McGreggor 29/09/06 20:32
    Re: Unbalanced Comparison? Jean-Marc Orliaguet 29/09/06 21:18
  the nail or the hammer Jean-Marc Orliaguet 29/09/06 19:22
  Zope 3 CA is a hammer, but not everyone sees nails Rocky Burt 29/09/06 17:51
Posted by Jean-Marc Orliaguet @ 09/29/2006 12:18 AM. -  7 comments