[SM]Plan...

Stephan Rudlof sr at evolgo.de
Sun Aug 8 15:14:23 UTC 2004


Hello All,

I'm back in front of the screen (have been absent for a few days); let's
jump into the discussion...


First I want to clearify definitions: in my model
- a CC is a tuple of numbers;
- what Göran has called CC1 below, means one *position* in this tuple
corresponding to one compatibility level (CL).

Confused?
Let me explain a little bit further.

The compatibility level table expresses compatibility of one version
*relative* to the previous one. A maintainer had to choose *one* out of
six from the compatibility level table.

The CC will be computed *incrementally* for each version, started with
the first (given CC (1, 1, 1, ...) as a start tuple). It is a
measurement for the compatibility of one version to *all* other ones!

It is easy to read the compatibility level information given by a
maintainer if you have two CCs: the one from the version you are
interested in and another from its previous version. Then the
compatibility level given by the maintainer is just the highest ranked
number in the CC tupel which has been increased (the lower ranked ones
will just be setted to number one (zero would be an alternative)).

The main idea behind this (why this tuple?) is to have some ordering of
compatibility levels: a change in the lower ranked compatibility levels,
should *not* affect the compatibility of the higher ones. If the
maintainer hints are correct, then this allows automatically upgrading:
given a requirement as dependency to some version with a CC tuple down
to some compatibility level (leaving the lower ranked ones out, getting
a shorter tupel as a full CC) allows increases in the last and all
positions behind.
For example: given a dep to some package P with a CC of (4, 2) would
allow package versions with CCs
  (4, 2, 1, 1, 1, 1),
  (4, 2, 7, 2, 3, 2),
  (4, 3, 1, 1, 1, 1),
  (4, 3, 7, 5, 6, 3),
  (4, 9, 2, 2, 1, 1);
but *not*
  (5, 1, 1, 1, 1, 1) (to high),
  (4, 1, 1, 1, 1, 1) (to low).


Now my other explanations should become more clear.
Note: I have updated the 'compatibility code' Swiki page
  http://minnow.cc.gatech.edu/squeak/3792
accordingly.

goran.krampe at bluefish.se wrote:
> Hi guys!
> 
> "Andreas Raab" <andreas.raab at gmx.de> wrote:
> 
>>Hi Guys,
>>
>>Just out of curiosity: Why is it necessary to go to the length that you are
>>proposing with respect to the compatibility levels? It seems to me that a
>>maintainer might be hard pressed to distinguish between CC 1 and 2 (I
>>couldn't possibly imagine that absolutely no app would ever be able to use a
>>changed package; so I'd probably always opt on the side of 2) as well as 3
> 
> 
> Well, an example of CC1 would be if you have changed the core (=that all
> clients must use) API so that clients *must* changed. In short - this
> level means "It doesn't work, trust me, and the only reason you would
> like to try is if you want to fix your client!".
> 
> CC2 on the other hand also has changes in the API, but depending on what
> parts of the API that the clients use, they may be lucky and *may* work.
> So this one means "It has a chance of working, but you will just have to
> try it."

Agreed. CC1, CC2 read as compatibility level 1 and 2 (CL1, CL2).

> 
> So the distinction here is important for the user - CC1 doesn't invite
> you to "test and see if it works". It only invites developers to fix it.
> The chance that it would work is immensely slim and is based on that the
> maintainer simply is wrong and it should have been marked CC2. :)
> 
> CC2 on the other hand is the highest level of "incompatibility" and the
> maintainer wants to tell you that the chances of success with an old
> client are slim, but who knows - people win the lottery sometimes - it
> still *is* possible. :)

There is another aspect: for 'general' packages, where a client does not
use any API (e.g. a WebBrowser needed for viewing some elsewhere
generated HTML), a change in CC1 (first number in the CC tupel,
corresponding to compatibility level CL1 chosen by the maintainer),
expresses a bigger change in the package than a change in CC2 (CL2
chosen by the maintainer). And if some (general) functionality is
needed, it is possible to express the minimal needed one (assumed that
it increases from version to version): therefore in general CL1 would be
the best, since a requirement expressed as a requirement to a CC with
fixed CC1, CC2 (first two entries of the CC tuple given) would forbid an
increase in CC1 after my model (subset property).

> 
> Btw, my take on these levels (and currently in effect on SM) are here:
> 
> 	http://map1.squeakfoundation.org/sm/category/cb51b604-bb97-415d-a040-f2
> 31ecdd5bc7
> 
> Unfortunately my level list is reversed - but you guys are smart. :)
> 
> 
>>and 4 (how exactly do we define "not changed any old code"?)
> 
> 
> To me CC3 means that the maintainer thinks it should be compatible, but
> he has made changes.
> CC4 tries to distinguish the fact that only extensions have been made.

More exactly:
CL3 allows extensions *and* changes for improvement (e.g. being faster)
in code needed for older functionality, CC4 just extensions *without*
any code changes in code needed for older functionality (except fixes).
For example: think of an image processing library, where new image
processing function are introduced with a new version. This could be
made with or without code changes in the older image processing functions.
After both CL3 and CL4 the package has been declared to be compatible
with its previous one, but CL4 reduces the risk of *newly* introduced
bugs: in CL3 the improvements of older code could introduce new bugs there.
The code extensions (e.g. new lib functions) allowed after both CL3 and
CL4 shouldn't affect the compatibility to clients written for older
versions.

> Hmmm, I am also unsure here - but mostly because I may want a slightly
> another way to distinguish:
> 
> In my categorization I used a variant - I wanted to separate the "only
> bug fixes" from "changes yes, but not expected changes in external
> behavior". If you fix bugs, you *do* change the external behavior - but
> it can be considered to be changes of the "friendliest kind" hopefully
> for the better! :) That seems to me to be the highest compatibility,
> given that the API still *has* changed (=it behaves differently).
> 
> If you do *not* change external behavior, you may still have made a lot
> of internal changes - refactorings, new algorithms etc. So LOTS has
> changed, risks are high, but the external API is still not modified -
> the external contract is intended to be the same. So that seems to be
> the highest level of changes given that the external behavior is still
> the same.

Here is the main difference between my and Göran's model:
CL5 is for fixes and CL3 and CL4 for downwards compatible packages, so
fixes are lower ranked as downwards compatible packages in my model.

Imagine you are looking from a package client POV (also see
corresponding table at the Swiki page): normally you at least want to
have *all* fixes to this package, since they are expecting to just
making the behavior of it better. You would express a dependency to the
serving package to e.g. CL3 or CL4 (this means to give a requirement to
a CC tuple from the first CL1 down to these ranks)) to allow fixes. But
possibly you fear improvements in older code (could introduce *new*
bugs!) or - somewhat paranoid or not trusting the package maintainer
very much - even extensions of it. Then you would express a requirement
to a CC tuple down to the 5'th rank (CL5), just allowing fixes.
Automatically upgrading in mind I have made this ordering to allow fixes
while not allowing the other changes.

One exception though: if some client has made a workaround for a bug,
then the potential fix could break this workaround! This would be the
rare case, where the dependency could be stated such, that even fixes
are forbidden. But this is evil and should be avoided: best would be to
make the fix in the serving package and to change the workaround in the
client one.

> 
> Obviously there are different ways to do this. The most important aspect
> is of course that we - the maintainers - understand the model *and* that
> the users (well, mostly that's we too) do too. :)

Another important aspect is to have a well suited ordering of the chosen
compatibility levels for automatically upgrading.

> 
> 
>>or 5 and 6. It
> 
> 
> Well, level 6 seems a pity to not distinguish. 6 means no *code*
> changes, and could actually be machine verifiable. My proposed level 5
> was "no changes to existing code, only additions". Because I considered
> that to be the changes that would have the least probability of breaking
> things.

I'm considering fixes as the second lowest changes after *no* changes in
code at all.

> 
> 
>>seems to me that we might be able to simplify this by saying we have three
>>major compatibility levels:
>>* interface/semantics unchanged (known to be compatible) (5 and 6)
> 
> 
> 6 must be compatible, otherwise the maintainer is either lying :)

Exactly!

> or...
> well. In theory clients could depend on non-code elements of the code -
> but *that* would be like cheating. :) Hehe, I just remember that
> HttpView actually uses the method categories at one place - ok, sure,
> but still... :)

In this case I would treat a change in the method categories as a code
change (but nevertheless this sounds evil, since how should other
maintainers know, which other package relies on which method category
names?).

> 
> 
>>* interface/semantics (expected to be) compatible (3 and 4)
> 
> 
> I think a distinction showing me *something* about the likelihood of
> success would be nice.

Agreed.
It is good to be *able* to say: 'I do not want to have changes in the
code I'm using as a client at all!'
Though it is not the suggested normal behavior for expressing
requirements, since it inhibits development by making compatibility with
other packages worse.

> 
> 
>>* interface/semantics (expected to be) incompatible (1 and 2)
> 
> 
> Well, I still think that "expected to be incompatible" is different from
> "it is incompatible, trust me, it doesn't work - no, listen, I am
> telling ya, it *can't* work!" :).

Agreed.
But in case of needing a stable API both CLs are not suited as
requirement CLs.

> 
> 
>>With possibly being able to further distinguish (if that is needed). At
>>least for me, describing the compatibility level by using the above three
>>levels would be much simpler than the six levels proposed and (judging from
>>practice) these are precisely the levels that I typically care about as a
>>client.
> 
> 
> Well, we may never totally "agree" on this, :) but I am being "lenient"
> in this because in my model these levels are meant as guidelines for the
> user - they should give him guidance on the chances of things breaking
> or not. So it is not the end of the world for me if it doesn't come out
> exactly the way I would have liked it to. :)

> 
> Let us see where Stephan takes this, I am confident he will take the
> feedback on this thread and remold it into something we all can agree
> on. And then we will just see how it plays out.

For me it is important to save the subset ordering property of CLs for
automatically upgrading. If there is one level more or less is
secondary, though currently I think the proposed six ones have the right
granularity.


Greetings
Stephan

> 
> 
>>Cheers,
>>  - Andreas
> 
> 
> regards, Göran
> 
> 

-- 
Stephan Rudlof (sr at evolgo.de)
   "Genius doesn't work on an assembly line basis.
    You can't simply say, 'Today I will be brilliant.'"
    -- Kirk, "The Ultimate Computer", stardate 4731.3



More information about the Squeak-dev mailing list