Using interfaces in a Plone Product

published Jun 01, 2007

The eXtremeManagement product has seen lots of updates recently. I am writing a report for school about that. I will put the report online as a pdf file when it is ready. But I thought it would be nice to publish some parts in advance. Feedback can help me to make a better report. The intended audience is mostly Plone (partly Zope) developers. The teachers at school who are going to give me a grade for this should also be able to follow it though and they do not know much about Zope and Plone. So this blog entry and some others like it should be fairly readable also for programmers new to Zope and Plone (and python probably).

In Zope 3, interfaces are important. Interfaces are classes that define functionality. Other classes that claim to implement that interface should provide that functionality. The simplest kind of interface is the marker interface. An example is in interfaces/xmstory.py:

from zope.interface import Interface

class IXMStory(Interface):
    """eXtremeManagement Story
    """

It is called a marker interface because you can mark a class with it. Marking means that you claim that a certain class implements this interface. We do that in content/Story.py:

from Products.eXtremeManagement.interfaces import IXMStory
...
class Story(OrderedBaseFolder):
    ...
    implements(IXMStory)

On its own this does absolutely nothing. But now we can do something with this interface in other parts of our code. For example, in browser/configure.zcml we register a certain view or page only for objects that implement this IXMStory interface:


Details aside, this now means that the page with the name story is available exclusively for objects implementing that interface, instead of all objects, which would be much less clean.

As a first step it is enough to define marker interfaces for all our content types. So in the interfaces/ directory we have defined interfaces IXMProject, IXMIteration, etcetera.

Interfaces can be much more than just markers, though. They can define functionality. Objects that implement this interface then promise to provide that functionality. In the file timing/interfaces.py we define an interface like this:

from zope.interface import Interface
from zope.interface import Attribute

class IActualHours(Interface):
    """Actual hours and minutes worked
    """

    actual_time = Attribute("Actual time")

    def recalc():
        """Recalculate the total of bookings/actual hours.
        """

Any class that claims to implement this IActualHours interface must at least have an attribute actual_time and a method recalc. This is true for our Booking class, so we can claim to implement the interface. Instead of saying this in python code, like in the example for IXMStory above, let's now say this in timing/configure.zcml:


  

We will later see how this is used in practice.

Keywords
plone xm