STB Conundrum

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

STB Conundrum

Chris Uppal-3
Good afternoon, and a Happy New Year everybody.

Here's something that's puzzling me with STB versions:

Let's say we have two classes, ListView and TreeListView for example (ehem!).
TreeListView is a subclass of ListView.  ListView is at STB version 11.

I now want to change to a new layout for TreeListView instances, so I need to
create a new STB version number for TreeListView, and do the usual little dance
in #stbConvert:fromVersion:.  No real problem there.  Except...

What version number should I use ?  I need to allow for the fact that
ListView's STB version will probably change in future releases of Dolphin, but
I don't want to commit to updating TreeListView each time that happens (or even
having to bother to look see if it has happened).

The best I've been able to come up with is to make the "real" STB version of
TreeListView encode both the "local" version number (say, 1) and the
superclass's version number (11 in this case), and then decode appropriately in
#stbConvert:fromVersion:.  My first attempt uses:
        (localVersion * 997) + superVersion.
as the encoding, which (since 997 is prime) can be picked apart unambiguously
using #quo: and #rem:.  So I can call super stbConvert:From: with the
TreeView's version number (11), and then apply my own conversion using my own
version number (1).

I also have to be careful to refer to instvar indexes using #indexOfInstvar:
rather than hard-coding constants, but that's minor.

As far I can tell it does sort of work (i.e. I've tested it once), but it's
obviously fragile, and -- frankly -- rather baroque.

So, am I missing something about how STB works ?  Is there a better way ?  Will
the above technique even work at all ?

Any ideas, anyone ?

TIA.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: STB Conundrum

Blair McGlashan
"Chris Uppal" <[hidden email]> wrote in message
news:3e148409$0$154$[hidden email]...
> Good afternoon, and a Happy New Year everybody.
>
> Here's something that's puzzling me with STB versions:
>
> Let's say we have two classes, ListView and TreeListView for example
(ehem!).
> TreeListView is a subclass of ListView.  ListView is at STB version 11.
>
> I now want to change to a new layout for TreeListView instances,
....[snip]....
>
> What version number should I use ?  I need to allow for the fact that
> ListView's STB version will probably change in future releases of Dolphin,
but
> I don't want to commit to updating TreeListView each time that happens (or
even
> having to bother to look see if it has happened).
>
> The best I've been able to come up with is to make the "real" STB version
of
> TreeListView encode both the "local" version number (say, 1) and the
> superclass's version number (11 in this case), and then decode
appropriately in
> #stbConvert:fromVersion:......[snip]...

Unfortunately I don't think that will work, since it will mean that the
TreeListView stbVersion is always greater than the ListView version (unless
we are very prolific), and hence any STB conversion we implement in
hypothetical future versions of ListView will not get run for your
TreeListView instances because they have been saved with a larger version
number.

I don't know of an STB conversion technique for isolating oneself from
schema changes in superclasses, but please do share it if you think of one
:-)

Schema migration can be very tricky with STB, particularly when modifying a
class with subclasses that add further instance variables. This is just one
of the reasons we are intending to replace STB in the next release. Until
that happens a useful technique is to always allocate a spare inst var slot
or two to avoid the need for STB conversions caused by adding new inst.
vars. Obviously one should also avoid deleting or rearranging the inst vars.


Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: STB Conundrum

Christopher J. Demers
"Blair McGlashan" <[hidden email]> wrote in message
news:av58nn$c4ja8$[hidden email]...
...
> Schema migration can be very tricky with STB, particularly when modifying
a
> class with subclasses that add further instance variables. This is just
one
> of the reasons we are intending to replace STB in the next release. Until
...

This sounds interesting to me.  Is there further information available about
this, or is it still in the planning stages?  I am using STB as a file
persistence mechanism in an application I have developed.  I hope that the
STB replacement will continue to be (and perhaps be even more) suitable for
that purpose.

Chris


Reply | Threaded
Open this post in threaded view
|

Re: STB Conundrum

Chris Uppal-3
In reply to this post by Blair McGlashan
[It looks as if this didn't go out the first time -- apologies if you see it
twice]

Blair,

> Unfortunately I don't think that will work, since it will mean that
> the TreeListView stbVersion is always greater than the ListView
> version (unless we are very prolific), and hence any STB conversion
> we implement in hypothetical future versions of ListView will not get
> run for your TreeListView instances because they have been saved with
> a larger version number.

Well, it seems to work. I just tried saving a ListTreeView resource with my
current version number (1008, made of 1 local and 11 inherited), then bumping
the ListView version to 12, and adding the necessary boilerplate code with a
bit of tracing.  On restoring the View, the inherited conversion code got
called OK.

Here's the implementation of ListTreeView>>stbConvert:fromVersion:

======================
stbConvert: anArray fromVersion: anInteger
        "private -- convert from an earlier version by updating and answering
        the array of instance variables.  We have to be tricksy here, since
        we need to allow for both changes to *our* encoding and changes
        made (independently) in the super class.  See #stbVersion"

        | localVersion superVersion |

        "decode the two version numbers packed into anInteger"
        localVersion := anInteger quo: self stbEncodingPrime.
        superVersion := anInteger rem: self stbEncodingPrime.

         ^ self
                stbConvert: (super stbConvert: anArray fromVersion:
superVersion)
                fromLocalVersion: localVersion.
======================

(There is, btw, no real need to use a prime number for the encoding -- I
thought there was when I was writing it, but that was just me taking time to
scrape the rust off my brain after the break :-(  I was getting confused with
Godel numbers...)

> Schema migration can be very tricky with STB, particularly when
> modifying a class with subclasses that add further instance
> variables. This is just one of the reasons we are intending to
> replace STB in the next release.

Ah good, so the question becomes: should I just use a single new version for
my ListTreeView (say 12) and assume that there will never be any ListView
and MultipleSelectionListView saved with a higher version than 11 using the old
STB ?  I'd feel safer going ahead with my scheme for the time being, but if I
do that will I be making problems for myself with the conversion from old to
new STB ?

> Blair

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: STB Conundrum

Bill Schwab
In reply to this post by Christopher J. Demers
Blair, Chris,

> > Schema migration can be very tricky with STB, particularly when
modifying
> a
> > class with subclasses that add further instance variables. This is just
> one
> > of the reasons we are intending to replace STB in the next release.
Until
> ...
>
> This sounds interesting to me.  Is there further information available
about
> this, or is it still in the planning stages?  I am using STB as a file
> persistence mechanism in an application I have developed.

That makes two of us.  In fact, I use it in multiple applications.  STB does
suffer from problems with changes to base classes, but it is a great
serializer with very compact output.

D5 caused a small problem for me by adding an instance variable to one of
the color classes that I subclass for use in views.  IIRC, it required some
debugging during the package load to see what was wrong, making a suitable
patch, and then starting over with the patch filed in at the right time.
Hopefully I didn't make that sound like only one time through the loop :)
Otherwise, I try to avoid subclassing things other than Object, and either
version entire sub-hierarchies at one time, or in one case with lots of
fan-out I gave up and simply set down an edict<g> that the root class (a
subclass of Object) would never add instance variables.


> I hope that the
> STB replacement will continue to be (and perhaps be even more) suitable
for
> that purpose.

That makes two of us :)

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: STB Conundrum

Pieter Emmelot-2
In reply to this post by Blair McGlashan
Blair,
Might it be an idea to replace classnames with their GUID in the STB files
or have an option to resolve classes by GUID on file-in?
This way classes can be renamed without STB file-in problems like with the
view resources.

Regards,
Pieter

| Schema migration can be very tricky with STB, particularly when modifying
a
| class with subclasses that add further instance variables. This is just
one
| of the reasons we are intending to replace STB in the next release. Until
| that happens a useful technique is to always allocate a spare inst var
slot
| or two to avoid the need for STB conversions caused by adding new inst.
| vars. Obviously one should also avoid deleting or rearranging the inst
vars.
|
|
| Regards
|
| Blair
|
|