[Zope] incrementally improving a product?

Amos Latteier amos@aracnet.com
Mon, 15 Mar 1999 09:32:41 -0800


At 12:01 PM 3/15/99 -0000, julian@zereau.net wrote:
>If I build a product, deploy instances of it, and continue editing and
>reloading the product, will its instances be improved or will they be
frozen at
>the state they were in when created?

Zope's object database uses Python's pickle facility, so in general
instances only store their own data, and use whatever version of the class
is available. Classes are not stored in the database. This means that when
you change your class, your instances will be updated.

>Also, is there any problem with the instances failing to work with a newer
>product version?

Yes. And this is not a Zope-specific issue, or even a Python-specific issue.

Anytime you have long-lived instances and change the class, you may run
into problems. Python comes with a couple hooks to help you out. You should
look into __getstate__ and __setstate__ which are documented in the Python
pickle documentation.

Probably the most common type of problem occurs when your new class
definition assumes a new attribute which the old instances don't have. An
easy way to solve this is to provide a class attribute which gives a
reasonable default for this attribute.

For example:

class MyClassV1:
  'Original class'

  def __init__(self):
    self.color='red'


class MyClassV2:
  'Updated class'

  def __init__(self):
    self.color='red'
    self.texture='bumpy'

  def describe(self):
    return 'I am %s and %s' % (self.color, self.texture)

Notice that instances created with MyClassV1 will not have a 'texture'
attribute, so that when the class is updated, old instances will break when
you call the new 'describe' method. A simple fix is to provide a default
class attribute. For example:

class MyClassV2:
  'Backward compatible updated class'
  texture='nondescript'
  ...

Now old instances won't break in the 'describe' method.

Another approach is to test for the attribute and update the instance when
you're going to use it. For example:

  def describe(self):
    if self.texture=='nondescript':
      self.get_texture()
    ...

If 'describe' is the only place where you use 'texture' then you wouldn't
even need to provide a class attribute, and could simply test for the
absence of the attribute.

Finally you might include version numbers in your instances and test for
these, but this seems like overkill. I would suggest sticking to default
class attribute solution for most cases.

Hope this helps, and good luck.

-Amos