What are the pros and cons about declaring package version methods in Perl?

488 Views Asked by At

Modules are cool especially when they come with versioning. You can define minimum module version to prevent leak of methods you want to use. But with every light side there comes a dark side which means Perl's TIMTOWTDI.

After nearly seven years as a Perl developer I saw and wrote version declarations in many ways. Some are easily to point as bad, some not. As no one can know a language completely I would like to ask you guys whats the pros and cons of the following software versioning in Perl is.

Please don't hesitate to comment more ways of version definition if you find one leaking ;)

Please respect:

  • weird require/use of module that may cause trouble detecting module's version (compile vs runtime)
  • PAUSE/CPAN parsing (and other common services)
  • readability for end users
  • maintainability for developers

What are the pros and cons about declaring package version methods in Perl?

Method 1

package PackageName;
BEGIN {
  use version 0.77; our $VERSION = version->new('v0.0_1');
}

Method 2

package PackageName;
BEGIN {
  our $VERSION = 0.000_01;
}

Method 3

package PackageName;
BEGIN {
  our $VERSION = 0.0.1;
}

Method 4

package PackageName;
use version 0.77; our $VERSION = version->new('v0.0_1');

Method 5

package PackageName;
our $VERSION = 0.000_01;

Method 6

package PackageName;
our $VERSION = 0.0.1;
3

There are 3 best solutions below

12
Mithaldu On BEST ANSWER

The correct answer is, do this:

package My::Thing;
our $VERSION = "0.001";

The version should always be a decimal number, using the three-digit split convention. The above version would be shortened to v0.1.0, to change the 3rd step in that abbreviated form you would define your version like this: 0.001001, which would be v0.1.1 abbreviated.

Do not put underscores into your version number to mark dev releases. The Perl toolchain has since adopted the -TRIAL mechanism, as exemplified by Dist::Zilla 4.101800-TRIAL. The advantage of that is that the version numbers in your code need no changes. Only the release filename and meta files are modified from the norm by adding -TRIAL.

Edit:

After reading daxim's answer and pondering a bit, i have to agree on putting the version number in quotes. It does not change the functionality in any way, but reduces the chances of 0.00101 being mistaken for v0.1.1, when it is in fact v0.1.10 and is more clearly read as 0.001010.

7
ikegami On

4. Good. Using version will have fewer corner cases.
5. Ok.
6. (Short for v0.0.1) Let's avoid v-strings, please?

The BEGIN does make a difference (populate $VERSION before the following lines are compiled), but that difference is useless.

2
daxim On

Best practices according to me after lurking years in #toolchain and various module-related mailing lists.

examples

For modules:

package Foo::Bar 2.001; # 2nd version of revision 2
package Fnord 2.420;    # 421st version of revision 2

Otherwise:

our $VERSION = '2.001'; # 2nd version of revision 2
our $VERSION = '2.420'; # 421st version of revision 2

rationale

Every module must have a version or else it is problematic to accurately specify a dependency when a distribution is split. It works best when the distribution version and each module's version are equal and increased in lock-step. To to make this easy, use perl-reversion, which is part of Perl::Version. Increase a version each time when you need to depend on a new features or a changed API from code external to the distribution.

When using the package declaration, a version is a rational number. If a package declaration is not suitable, declare the magic $VERSION variable and then a version is a string.

In any case, the version consists of a revision number, a literal dot as separator and a version number, altogether in the form y.xxx. y is a natural number, xxx are exactly three zero-padded digits. String quoting prevents trailing zeroes from disappearing. Padding to the same amount of digits prevents confusion about 1.10 < 1.9. Having exactly one separator prevents confusion about 5.10.1 == 5.010001.

Do not use the version module for declaring versions. Using plain strings prevents that ugly v prefix in a distribution tarball name. However, using the module to handle versions, e.g. for comparing them, is a good idea.

Do not use v-strings. They are poorly understood.

Do not use underscores. Using underscores require to eval the version to turn it into a number. If you want to mark a distribution as release candidate to the PAUSE indexer, add the word TRIAL to the distribution name.

A version should be accessed through the universal VERSION class method only.

perl -mLWP::Simple -E'say LWP::Simple->VERSION'

compliance

This scheme is fully compatible with the advice laid out in

It is incompatible with semver.