[Zope] Products vs. ZClasses- Design Question

Jeff K. Hoffman jeff.hoffman@goingv.com
Fri, 16 Jun 2000 17:16:14 -0400 (EDT)


On Fri, 16 Jun 2000, Garrin Kimmell wrote:

> Hello,
> 

[snip]

> I've thought of three ways to develop the class:
> 
> 1. Develop the entire class as a Zope product in Python.
> 
> The advantage I see here is that developing the application logic is
> fairly straightforward with Python. I see problems, though, with the
> user interface, especially if I want to make changes to it after
> instantiating a few objects. It is my understanding that objects created
> from a Product are not automatically updated when changes are made to
> the class methods (as opposed to ZClasses, where they are). Am I correct
> here?

The user interface for a Python Product is generally specified in .dtml
files distributed with the Product. If you change one of these .dtml
files, all you have to do is restart Zope and you will see the changes.
Whether you have created one instance, or one hundred instances, they will
all change their interface.

What will *not* change (without a little help from you, described below)
are the attributes that have been added or removed from the class. In this
case, new instances will be configured with the new attributes, while old,
previously instantiated instances will retain their old attribute
configuration.

To migrate your existing instances to the new configuration, you need to
write a __setstate__() method in your class, for example (untested):

class MyPersistentClass(Persistent):

  def __setstate__(self):
      Persistent.__setstate__(self, state)
      if not hasattr(self, 'newAttr'):
          self.newAttr = newValue
      if hasattr(self, 'deprecatedAttr'):
          del self.deprecatedAttr

Each time the object's state is loaded from the ZODB, this method will be
invoked. If a previously instantiated instance of your object is loaded,
and does not contain an attribute called newAttr, it will be created.
Likewise, if it contains an attribute called deprecatedAttr, it will be
removed.

ZClasses provide no such facility. You cannot upgrade ZClass instance
attributes automatically, as far as I know. You'd have to write a script
to go through your ZODB and upgrade the old instances manually. Boo.

> 2. Develop the entire class as a ZClass
> 
> The principal advantage I see is that changes to the class
> methods are dynamically updated in all instances of that ZClass. The
> problem is that DTML is (for me, at least) a pain in the ass to write any
> complicated application logic with.

As explained above, this advantage is shared by Python Products also. You
do *not* want to write application logic with DTML. At a minimum, use
Python Methods. Otherwise, use Python.

> 3. Develop the application logic as a Product in Python, then use that
> class as a mix-in class for a ZClass that implements UI logic with dtml
> methods. 
> 
> This seems to be the best solution (even if it is the most work). I should
> get the advantage of having ZClass instances automatically update changes
> to ZClass methods, while having the programability of Python for 
> application logic in the Product. If I do take this route, are there any
> quirks I should be aware of when inheriting a ZClass from a product?

This is a good way to go, and provides a nice advantage over vanilla
Python Products: You do not have to restart Zope to see changes to your
UI.

However, you cannot reparent a ZClass after it has been created. Well, you
can, but no one is very happy with the ways you have to do it. So, if you
are a fly by the seat of your pants kind of coder, don't do it. If you do
all of your analysis up front, and will know in advance exactly which
classes your ZClass will inherit from, go for it. But, should you miss
something in your analysis, you will have to reparent your ZClass and
endure the pain involved with that process.

> I am new to Zope and would appreciate any insight into the tradeoffs
> among these three strategies. 

In summation, Python Products are, by far, the most flexible solution. You
can upgrade them. You can write all of your logic in Python. You write 
your UI in DTML. You can manage all of this using CVS (or the version
control system of your choice). Good stuff.

Using ZClasses for your UI can allow you to see updates to your UI in
realtime without having to restart Zope. In addition, ZClasses make your
UI accessible to people who do not have access to the filesystem of your
Zope server. You cannot easily use CVS with ZClasses, since they are
stored in the ZODB and not the filesystem.

Hope this helps!

> Thank you,
> Garrin

--Jeff

---
Jeff K. Hoffman                               704.849.0731 x108
Chief Technology Officer                      mailto:jeff.hoffman@goingv.com
Going Virtual, L.L.C.                         http://www.goingv.com/