On Tue, Mar 3, 2009 at 2:29 AM, Robert K.
[email protected]wrote:
Well, certain things will just work. But you’ll trade this for different
issues. For example, all of a sudden you can have different implementations
of the same class coexist. I wouldn’t say that one or the other solution is
necessarily easier. They both do not change the complexity of the
underlying problem (evolution of code with data artifacts belonging to
different versions). Both approaches (i.e. storing code and not storing
code) make certain things easy and other things hard.
Ruby has some subtleties in this area when compared to other OO
languages.
Mike G. introduced the idea that this was a problem in dealing with
schema
migration. To me this implies dealing with layout changes to the
object.
This is a problem in most languages like Java, C++ and Smalltalk where
classes, along with whatever other language specific roles they play,
act as
a template for understanding which instance variable goes where in a
reified
instance.
This means that if you marshal an object then match it up to a class
with
the same template, you run into the danger of misinterpreting the state
of
the object. In systems written in these languages, you might be able to
get
away with two different versions of a Class which have the same instance
layout template but vary in method implementations, or even have
slightly
different method repertoires.
Ruby falls into the class of languages where classes DON’T act as
templates,
instead instance variables are dynamically bound to each instance with a
run-time lookup used to map instance variable names to location.
So the OP’s case shows that you can marshal Ruby objects and the
‘schema’ is
carried with each object. It’s just that accessor methods don’t go
along.
As it turns out, the MagLev project is trying to figure out how to deal
with
a similar problem right now. In Gemstone Smalltalk, which is the code
base
on which MagLev is being built, classes and instances are all held in a
shared persistant store. When a process changes a class, and commits a
transaction, other processes see the change when the results of the
transaction become visible to them (i.e. when they start up, or commit
or
abort a transaction of their own).
Now, this was apparently the same model they were planning to follow for
MagLev. However, we had some discussions in the beta-testers forum about
how
this might or might not work with many Ruby programs because the Ruby
execution model builds up classes at run time from a known initial
state,
and classes change as the code executes, either through ‘normal’ class
method definition (both of which are execution time events in Ruby) or
through various levels of metaprogramming sophistication.
Because Ruby classes get built incrementally at run-time, the order of
execution can be important, so starting with a persisted initial set of
class definitions can be problematic at times.
So currently MagLev allows independent control over whether or not a
transaction commit persists changes to class definitions. A process
needs to
explicitly indicate that it want’s to put class definition changes into
the
state to be committed before committing.
We’ll see how this evolves.
–
Rick DeNatale
Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale