Modules
Alexandre Bergel
bergel at iam.unibe.ch
Sun Feb 27 18:15:43 UTC 2005
Dealing with class extension is very subtle. Approaches taken by Selector Namespace, Classboxes and Virtual Classes rely on bounding the visibility of class extension: the one who defines a class extension is the only one to see it. Conflicts are easily avoided in that way...
Cheers,
Alexandre
On Sun, Feb 27, 2005 at 01:11:31AM -0500, Colin Putney wrote:
>
> On Feb 26, 2005, at 11:20 PM, Florin Mateoc wrote:
>
> >>We have two versions of a method, both with complete version history.
> >>Because we have the version history, it doesn't really matter that
> >>the two versions come from different packages, it's exactly the same
> >>as merging two versions of the same package. So instead of one
> >>version overriding the other, we do a merge. By comparing the method
> >>histories we can decide if one version supersedes the other. That
> >>would mean that it's an updated version of the other, which means we
> >>can rely on the user's wisdom again. If the user changed the method
> >>from one of the versions we have to the other one, he must know what
> >>he's doing. Therefore we use which ever version the user has already
> >>chosen.
> >
> >
> >I am sorry, but this is simply not true. A developer may choose, in a
> >newer version of a class, to ignore some unrelated development, and
> >stick to an older protocol, by including some older versions for some
> >of the methods. This is not a made up example, I have encountered the
> >situation quite often. You can easily have, as a simplistic example,
> >PackageA>ClassB>methodC(version1),methodD(version2) and
> >PackageE>ClassB>methodC(version2),methodD(version1). The automatic
> >resolution will do the wrong thing, and it won't even inform the user.
>
> Ok, let's get into this in excruciating detail, because it's not clear
> to me why you think the above example cannot be resolved correctly.
> Let's say I have the following program elements, drawn from your
> example, with history.
>
> PackageA
>
> ClassB>>methodC.version1 (ancestors: version0)
> ClassB>>methodD.version2 (ancestors: version0, version1)
> ClassB>>MethodE.version1 (ancestors: version0)
>
> PackageZ
>
> ClassB>>methodC.version2 (ancestors: version0, version1)
> ClassB>>methodD.version1 (ancestors: version0)
> ClassB>>methodE.version2 (ancestors: version0)
>
> Ok, so let's see what happens if we load both packages into the same
> image. PackageA and PackageZ both define methodC, and they have
> different definitions. So we've got to decide which version, if any,
> will be in the image. The version in PackageA is called version1, and
> it was derived from version0. The version in PackageZ is called
> version2, and lists version1 as its ancestor. Therefore, version2 was
> created by modifying version1. So we'll choose version2, from PackageZ.
>
> MethodD has the reverse situation. PackageA's version is a descendent
> of PackageZ's, so we'll choose version2 again, but this time from
> PackageA.
>
> MethodE presents a conflict. Both versions descend from a common
> ancestor, but neither descends from the other. So we pop up a conflict
> resolution window, and let the user decide what methodE should look
> like when both packages are present. This results in a new version,
> called version3. When we're done, the image looks like this:
>
> ClassB>>methodC.version2 (ancestors: version0, version1)
> ClassB>>methodD.version2 (ancestors: version0, version1)
> ClassB>>methodE.version3 (ancestors: version0, version1, version2)
>
> Now, you are correct to point out that, say, methodC.version2 might
> have been developed in PackageZ without PackageA loaded, and so might
> not work as PackageA expects. Perhaps we should indeed log to the
> Transcript when a merge automatically resolves overlapping packages.
> There is no *guarentee* that version2 will work right. But our chances
> of success are better if we follow the intention of the developer of
> version2, which was to replace version1. Following the order that
> packages are loaded is little different than choosing at random.
>
> >Making independently developed packages work together means
> >(intelligent) work, and if there's any overlap, the chances of solving
> >the issues automatically are, I believe, very slim, and versioning
> >does not help. Even if all the common methods in one of the packages
> >are newer versions (and descendants) of the same methods in the other
> >packages, it still doesn't mean that they are made to work with the
> >older package, it may simply mean that the newer package is supposed
> >to work with a newer version of the older package. I think the only
> >situation where you can say that there is no conflict is when the
> >common methods are all identical, and for this you don't need
> >versions. This is why, to my mind, overrides have nothing to do with
> >versioning, they are simply a different kind of extension.
>
> I agree that it takes intelligent work to make packages work together,
> and I'm not suggesting that the computer can do that. I am suggesting
> that, having done the work, we record the results so that we don't have
> to do it again everytime we load those packages.
>
> [snip]
>
> >>>This is probably just the memory of a frustration with Envy: because
> >>>it stores all these method editions (inluding every time you put a
> >>>"halt" in a method), the noise level is pretty high, so I always
> >>>wished that I could see at a glance, when looking at the list of
> >>>editions for a method, which editions are "real". But even if we
> >>>have explicit method versioning, so the noise is reduced, the most
> >>>"real" ones are the ones associated with the holder's version,
> >>>because there is an implicit minimal testing expectation for
> >>>versions.For the method version I would expect something like a
> >>>unit-test, for a class, the beginning of some functional testing.
> >>>The expectation is even higher for the package, because it usually
> >>>groups together classes working in tight coupling, so the testing
> >>>done for a package version is more of a functional test, so now
> >>>those methods "really" work. I guess it would be fun to disallow
> >>>versioning if we detect that testing was not performed :) Seriously
> >>>though, it might be interesting if we could link somehow versions to
> >>>the tests performed.
> >>
> >>
> >>Ok, I see. You just want to define a group of program elements that
> >>should be versioned together. With Monticello you do this explicitly,
> >>so there's a lot less noise. Everything is a "real" version, and they
> >>correspond to a bunch of other "real" versions that were current at
> >>the same time.
> >
> >Even if you do it explicitely, not all versioning happens at the same
> >time.
> >I develop a method, it looks good, I test it a little (workspace,
> >unit-test, whatever), I am happy with it and I want to keep it. I
> >version it (separately, because this is what method-level granularity
> >means).
>
> Interesting, because that's not what I mean by "method-level
> granularity."
>
> In MC1 (and Store, as far as I can tell), only packages have ancestry.
> The ancestry of a method has to be reconstructed by examing all the
> versions of the package it appears in and noting how it changes. In MC2
> (and Envy, as far as I can tell), methods have individually recorded
> ancestry. This is why I say that MC2 versions at method-level
> granularity.
>
> But that doesn't mean that you have to version new methods in
> isolation, whether explicitly or with every accept as in Envy. If you
> do that, you loose the spacial context I mentioned in my last post.
> That version is just noise, so why bother? It's not like the method is
> going anywhere. You can save your image without versioning it, and even
> if you manage to crash the VM you can always pull it out of the change
> log.
>
> In MC1 you always version whole packages at a time. MC2 is more
> flexible, in that you can specify other ways of separating the code you
> are interested in from the rest of the image. But whatever your method
> of segregation, you always version all of it at once. So in this sense,
> Monticello versions at "project-level granularity," the project being
> whatever you're working on, be it a package, change set or whatever.
> It's important to do that so as to get the spacial context needed to
> merge snapshots correctly.
>
> Colin
>
>
>
--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel http://www.iam.unibe.ch/~bergel
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
More information about the Squeak-dev
mailing list
|