Hi!
Mariano, yes, I forgot to say that B is subclass of A.
Henry, thanks a lot for sharing your knowledge about BOSS. Following my
example, the "backwards-compatability reader method" has to be defined in
A, right? Or do you specify it as a parameter to the class loader? I would
like to have automatic tolerance to simple layout changes like this.
Eliot, thanks for the correction. Rescan the methods seems to be a nice
solution, and has not dependency with compiler.
The migration service you describe makes me think, because we have recently
added migration support to Fuel; it works like:
aMaterializer
migrateClassNamed: #OldPoint
toClass: NewPoint
variables: {('x' -> 'posX'). ('y' -> 'posY')}.
On one hand, in simple cases it should be more efficient than creating a
dictionary for each instance and then become them. On the other hand, in
more complex cases it's not enough and the dictionary could be a more
uniform solution. For example, if NewPoint has just a variable named
"coordinates", which points to an array with x and y as elements.
Martín
On Tue, Mar 6, 2012 at 3:27 PM, Eliot Miranda <[email protected]>wrote:
>
>
> On Tue, Mar 6, 2012 at 3:05 AM, Henrik Johansen <
> [email protected]> wrote:
>
>>
>> On Mar 6, 2012, at 12:03 PM, Henrik Johansen wrote:
>>
>> >>
>> >
>> > Parcels
>> > - Check a hash based on class layout vs equivalent hash for the stored
>> method's class (stored with the method).
>> > If different:
>> > 1) check for existence of a backwards-compatability reader method, hand
>> the old instance to it, and expect the old instance to be #become'd into
>> something current,
>> > 2) raise an error if no such method exists.
>> >
>> > Now, the main problem with this scheme is it's left as an exercise to
>> the user to come up with a procedure to ensure said backwards-compat reader
>> method stays up to date as additional changes are made.
>> >
>> > Is it a big problem?
>> > Depends on your tests, and programmer diligence at any given day.
>> >
>> > Added inst vars are not a big deal, as if you forget them, there will
>> usually be a nil #DNU somewhere down the line. (or you use lazy
>> initialization, and everything works as expected even for existing
>> instances)
>> >
>> > Removals/reorderings are a bigger issue, as the detection of failure
>> (inst vars in wrong slots) are often far removed from the source of
>> problems (forgetting to update the reader method),
>> > If seldomly used, it may even go unnoticed until the instance is next
>> saved, at which time you're in real trouble (especially if saved alongside
>> newly created ones, in which case there is no consistency).
>> >
>> > In general I think it's an ok scheme, but would like to see a solution
>> more resilient to user-error.
>> > How to achieve that is an interesting topic, which I haven't yet found
>> time to think through as thoroughly as I had wished/intended some months
>> ago. :(
>>
>> Errr, BOSS, not Parcels.
>>
>
> Right. What Parcels do is shape-change instances *and* rescan methods to
> fix up inst var offsets. When a parcel is saved the "signature" of classes
> of instances there-in are saved so that the parcel contains all the inst
> var names of the class and its superclass. If on load the superclass chain
> has a different set of inst vars then lost inst vars are omitted and added
> inst vars are nil in the materialized instances. If a Parcel contains a
> full class (not just instances) that has methods, and the superclass chains
> inst vars have changed then these methods are "rescanned" (disassembled,
> and reassembled, not using the compiler) and inst var offsets are fixed up,
> missing inst vars getting changed into undeclared variable references (I
> think; at least this is what *should* happen; its what happens when one
> removes an inst var that is still referenced from methods).
>
> What's missing in the parcel scheme is any hook to allow the user to
> process shape-changing instances with the values of lost inst vars in hand.
> Presumably there will be cases when those values are essential to any
> schema migration. Personally I would want to decouple schema migration and
> add it as a post-processing step, which would imply that the materializer
> would offer a service (materialize in a special mode) where it constructed
> a dictionary from materialized and shape-changed instance to in parcel
> state (e.g. an Array of inst var values as they occurred in the parcel).
> Then the materialized instance could be migrated after the fact, with the
> default behaviour being analogous to what the system does now on class
> redefinition (values of deleted inst vars are lost, aded inst vars are nil).
>
> This reminds me of a bug with the ClassBuilder/RefactoringBrowser
> combination. If one refactors pushing an inst var up to a superclass or
> down to subclasses, the values of te inst var in instances are lost because
> the class change is in fact done as two changes, a deletion followed by an
> addition. This again could be fixed in a wrapper, building a dictionary
> from instance to values, performing the set of class changes, and then
> restoring the inst var state from the dictionary.
>
>
>
>> My bad.
>>
>> Cheers,
>> Henry
>>
>>
>>
>
>
> --
> best,
> Eliot
>
>