[DB-SIG] Modifying methods or attributes of persistent objects

Chris Cogdon chris at cogdon.org
Fri Aug 13 09:51:27 CEST 2004


On Aug 12, 2004, at 14:40, roy wrote:

> Hi:
>
> I am attempting to implement a small project using persistent objects
> (pickle). This works fine for storing a small class hierarchy, 
> however, I am
> seeing a problem emerging when, as the project evolves, I see the need 
> to say
> add new methods, or possibly add new attributes. for persistent objects
> ALREADY stored earlier, these new methods or attributes are not 
> defined.
>
> This seems to be a major maintenance issue. What if down the road I 
> have a
> well establised application, with fairly large database of objects. 
> Now I
> want to create a new version, which has new methods, etc. I see no 
> easy way
> to do this, other than to delete the entire database (pickled in this 
> case)
> then add the whole class hierarchy and however many instances I had 
> stored
> earlier.
>
> Am I missing something? Is there a cleaner, easier way to upgrade an
> application with enhanced objects? I think that conceptually it doesnt 
> matter
> what kind of database implementation one has here, whether it is a 
> RDBMS, a
> simple pickled store or whatever, the fact remains that previously 
> created
> objects cannot (easily) acquire new attributes and methods.
>
> Anyone have ideas on this issue, or can you point me to something in 
> the
> documentation which discusses this?

Actually, I dont think this will be a problem. Methods get attached to 
the class, and not the objects... as long as the class doesnt move from 
the module it's defined in, once you unpickle the objects, the new 
methods will be available for those objects.

Of course, you shouldn't try and pickle the class itself :)

One thing you DO need to consider is what attributes get attached to 
the OBJECTS themselves. This can be solved by ensuring that the class 
has reasonable defaults for all the objects.

Here's an example:

class C:
	a = 0
	b = 0
	def fn():
		pass

c1 = C()
c1.b= 2

In this case, when you pickle c1, what gets stored is 'this data is an 
instance of class C, and has an attribute 'b' with the value 2'. Since 
'a' hasn't changed, it doesn't get pickled, because there's no 
attribute 'b' IN 'c1' at the moment. Any access to 'c1' is deferred to 
its class.

Now, lets say your program changes, and C now looks like.

class C:
	a = 0
	b = 0
	c = 1
	def fn():
		pass
	def fn2():
		pass

When you unpickle your 'c1'. And you query either 'a' or 'c', in both 
cases the result is deferred to C, while accessing 'b' will get the 
object itself's version.

So... it should all be good, as long as you dont move 'C' from one 
module to another, and you have good defaults set in your class for all 
the attributes... or at least NEW attributes.

If things get really funky, you can always define methods for picking 
and unpickling objects, but in most cases you wont need to.


Hope this helps.



-- 
    ("`-/")_.-'"``-._        Chris Cogdon <chris at cogdon.org>
     . . `; -._    )-;-,_`)
    (v_,)'  _  )`-.\  ``-'
   _.- _..-_/ / ((.'
((,.-'   ((,/   fL



More information about the DB-SIG mailing list