On Wednesday 28 January 2004 05:28, David Manura wrote:
> I'm not sure branching maps cleanly onto the interface versioning scheme as 
> shown above.  Let's say you have 1.2.  You then branch to 1.2.1.1 => 1.2. 
> Meanwhile, in your main trunk, you create 1.3 => 1.2.  OK, now back in the 
> branch, say you want to introduce an incompatible change to 1.2.1.1.  There 
are 
> actually two ways in which your change can be incompatible: with respect to 
> 1.2.1.1 only or with respect to 1.2.  You provided an example of the first 
case, 
> where we introduce 1.2.2.1 =/=> 1.2.2.1 yet 1.2.2.1 => 1.2.  However, what 
shall 
> we do if we need to introduce a change incompatible with 1.2?  Number it 
1.3? 
> We can't do that because 1.3 has already been assigned in the main trunk.

The next version that is not automatically compatible with 1.x is 2.1 . This 
is true in your original scheme and in my version with branches.

If you have branches then the next version that is automatically compatible 
with 1.2 but not with 1.2.2.1 is 1.2.3.1 .

> Maybe the branch numbers should be of the form
> 
>    x.y.b.u.v
> 
> where x.y is the main trunk revision, b is the branch number, and u.v is the 
> branch revision.  For simplicity, we'll also eliminate the distinction 
between 
> changes that are incompatible only with the current branch revision and 
changes 
> that are incompatible with the main trunk revision.  The scheme for x.y will 
be 
> exactly the same as, yet independent of, the scheme for u.v.  So, the 
following 
> relations are implicit:
> 
>    1.2.1.1.1 ===> 1.2
>    1.2.1.1.2 ===> 1.2.1.1
>    1.2.1.2.1 =/=> 1.2         (note!)

why is this =/=> when ...

>    1.2.1.2.2 ===> 1.2.1.2.1
>    1.2.2.1.1 ===> 1.2         (a second branch)

... this one is ===> ?

>    1.2.2.1.2 ===> 1.2.2.1.1
>    1.2.2.2.1 =/=> 1.2.2.1.2
>    1.3       =/=> 1.2.b.u.v   for all b, u, v
>    1.3       ===> 1.2
> 
> This seems workable, but it's getting more complicated.  The question is, 
will 
> anyone use this?  Also, are numbers the best way to express this 
information? 

It's certainly confusing me and I don't think it will be widely used.

> The branch identifier 1.2.1 might alternately be labeled something more 
> meaningful like "unstable."  So, the above scheme might be rewritten
> 
>    unstable-1.1 ===> 1.2            (must be declared explicitly)
>    unstable-1.2 ===> unstable-1.1
>    unstable-2.1 =/=> unstable-1.2
>    unstable-2.2 ===> unstable-2.1
>    mycopy-1.1   ===> 1.2            (must be declared explicitly)
>    mycopy-1.2   ===> mycopy-1.1
>    mycopy-2.1   =/=> mycopy-1.2
>    1.3          =/=> unstable-*.*   (unless otherwise declared explicitly)
>    1.3          =/=> mycopy-*.*     (unless otherwise declared explicitly)
>    1.3          ===> 1.2
> 
> Now, say after merging unstable into 1.4 that you want to branch again, then 
you 
> just declare this explicitly and continue:
> 
>    unstable-3.1 ===> 1.4
> 
> Use of branch names rather than branch numbers will also reduce the 
possibility 
> of conflicts when there is no central assignment of branch identifiers (e.g. 
> when I create my own private version of a standard module and name the 
branch 
> "davidm", unbeknown to the module author).

Yes, once you stop trying to do numerical things to version strings (namely 
expecting < and > to mean something) then you are no longer forced to use 
numbers, you can use something more expressive. However numbers are still 
very common and already have some useful meanings so I want to get the 
numbers out of the way first and then consider more general strings.

> I was thinking making only "imp1.imp2_bug1.bug2" part of the identifier for 
the 
> distribution file to download, as is currently the case.  So, as usual, 
people 
> can say "I need to download MyModule-1.2_3," and this will uniquely identify 
the 
> correct file to download.  The interface number (or *multiple* interface 
> numbers), however, will be embedded, possibly hidden, inside the module so 
that 
> "use" will work correctly.  The interface numbers might exists as well in 
the 
> POD to give the user a heads-up, but this is not strictly necessary (if 
there's 
> a problem, the module user will find out upon compilation).  Although not 
> required and maybe not always practical, the module author may even attempt 
to 
> synchronize the implementation number with the interface number to make 
things 
> simpler. Therefore, 1.x implementations will implement 1.x versions of the 
> interface, while 2.x implementations will implement 2.x versions of the 
> interface.  This may be possible since the module author has full freedom in 
> assigning implementation version numbers (except for the requirement that 
they 
> be strictly increasing).

I can think of 2 disadvantages to not using the interface revision in the use 
statement and in the distribution name.

1 The user will get no compatibility information by just looking at the 
version. This can also be the case with the interface version but there are 
many cases where for example the user can immediately say "it's 1.3 and I'm 
writing for 1.2 so that's ok to install". Putting the information in the POD 
or metadata makes that harder.

2 There will be more implementations than interfaces so we would need to 
declare and store more compatibility information. I think we would also need 
to keep metadata about more modules. When using implementation versions as 
the key, if a CPAN deletes a version, they must still have keep the meta data 
for that version so that anyone asking that version can figure out what 
hidden interface value. Whereas if everyone is requesting interface versions 
then I don't have to keep any meta data around for delete distributions.


> I question, though, why you would want to specify implementation versions, 
> instead of just interface versions, inside the use statement.  If a module 
> implements the correct interface, it -theoretically- should work.

In general it's a bad idea but you may want the version that uses XML::Twig 
instead of XML::Parser for some reason.

I'm going to stop thinking about this issue just see if I can get the basics 
work well and sensibly.

> Here's a question: If only 
> implementation 2.0 is installed, and this implements interface 2.3, then 
will 
> the following fail or succeed?
> 
>    use MyModule 2.3_1.0;
> 
> (I believe it should succeed.)

It should be for the user to decide and I think you have to assume they really 
really wanted 1.0, otherwise what was the point of mentioning it?

> > If I've released 5.2_1.2 and 6.7_1.2 which one am I referring to in he 
"use" above?
> > Bugfix numbers would have to be unique.
> 
> Just to make sure we're on the same track (it starts to get confusing :)), 
the 
> 1.2 in the above use statement refers to the implementation number.  
Possibly it 
> should be clarified as this, at least for discussion:
> 
>    use MyModule qw(1.2impl);
> 
> I take 5.2 and 6.7 above to be interface numbers, and 1.2 to be an 
> implementation number.

Yes

> In this case, you're saying that implementation 1.2 
> implements two interfaces.

No. Right now, if I saw Module-5.2_1.2_1.tgz and Module-6.7_1.2_1.tgz I would 
not draw any conclusion from the 1.2 being in both of them because I'm used 
to thinking of version numbers as hierarchical but in your scheme you could 
not have the above because there can be only 1 1.2 implementation which is 
fine in itself but is different to the current way of doing things.

Basically we've gone from need the version string to be unique to needing the 
implementation+revision to be unique. Actually that's business as usual in a 
world where the interface version does not appear in the main version string.

> > I'll acknowledge one if you show me one :-) Version::Split is as lenient 
as possible given
> > the information at hand.
> 
> Correct, at compile time and "given the information at hand."  Actually, 
this is 
> not strictly correct: Version::Split -could- do deep source code analysis on 
the 
> module that uses it in order to obtain more info--very unlikely but 
"possible." 

When you throw eval into the mix you basically end up with the "halting 
problem" - can you write a computer program (call it Halt) that can predict 
whether another program will  finish or not. You can show that there is no 
program Halt that can do the job for every program you throw at it.

Of course Perl is a special case - you don't even have to get theoretical. I 
saw a program by Mark Jason Dominus compiles differently depending on the 
phase of the moon! That man needs help :-)

F

Reply via email to