Pay attention to versions of upriver dependencies

CPAN Riverdependenciesversions Sat 4 July 2015

When using someone else's module in our CPAN modules, most of us don't bother to specify a minimum version of that module. If no-one else is using your module you can get away with that. But as your distribution moves up the CPAN River, you should start paying attention, and specify minimum versions both in the code and your distribution's metadata.

My July assignment in the CPAN Pull Request Challenge was STEVAN's Path::Router. But FELLIOTT had already submitted a PR to switch it from Moose to Moo. Turning the tables on me, Stevan ended up giving me commit rights to his repo, so I could merge Fitz's PR. One of the things he suggested was making sure it required version 2 of Moo, since that addressed the concerns people had over fatal warnings. I ended up spending a lot of time looking at the Changes file for all the dists used by Path::Router, and thinking about minimum versions.

Works for me!

When using someone else's module in your code, I suspect most of us often just write:

use Foobar;

And in the prerequisites you'll usually see:

Foobar => 0

This effectively says "it doesn't matter what version", but what you're really saying is "it works with the version of Foobar I have installed here, on my operating system and my version of Perl". Sometimes you'll see someone specifying a minimum version, but my experience of that to date has been that it usually happens once you've been bitten. Or, I suspect, if you're cargo culting something you saw in someone else's code.

If my dists aren't being used by any others, I can probably get away with this. But as other dists start relying on mine, I think I owe it to them to start paying more attention to versions of the dists that I'm using. Other people are going to be on different operating systems from me, using different versions of Perl, and with random versions of other CPAN dists installed.

What version should I specify?

The trouble is, it's not always obvious what version you should require when you look at a dist, especially for larger dists. If you're using a function or method that was introduced in a particular release, then that's a good start point.

But then you should work through the Changes file and see whether there are any subsequent bug fixes or changes that you're relying on. If you're not sure, you could consider asking the author, or asking on IRC. You could also look at the dist's CPAN Testers results: if you see that all releases are green beyond a certain version, that's another useful data point.

I'm still trying to work out what the right approach is, but for the moment my thought is to work through the Changes file for each dist:

I realise that is a pain, but I've had a thought about that, which I'll write up separately.

Perl is a upriver dependency too

The version of Perl your dist requires depends on (a) the language features that you use, possibly (b) the version that you specify as a minimum version, and (c) the highest version of Perl required by your upriver dependencies.

It's not always easy to identify what version of Perl is required by your upriver dists. So you should make it easy for your downriver dists:

Versions of modules and distributions

When specifying a version with use, remember that you're giving the version of the module, not the distribution that contains it. These are often the same, but not always.

For me this is a good reason to follow these guidelines:

Dist::Zilla makes it easy to do this.

For example, consider the Mojo::Loader module which is part of the Mojolicious distribution. If you look at the source of Mojo::Loader, you'll see it doesn't have a $VERSION number (intentionally).

Release 6.12 of Mojolicious added the find_packages function to Mojo::Loader. If you're going to use this in your code, you should write:

use Mojo::Loader 6.12 qw/ find_packages /;

But you can't, because Mojo::Loader doesn't have a $VERSION.


I'm still trying to work out what the right thing to do is, but for the moment my new model is: when (considering) using a module:

Another option (see ETHER's comments below):

The downside with this approach is that you might not always be able to work out whether a failure is down to a specific version of one module you're using. If you're adding a new module dependency to an existing module, then this sort of experimentation should be done with a developer release. You won't see any knock-on effects on your downriver dependencies with the developer release though.

What cases have I missed?

comments powered by Disqus