CPAN dependencies and the river model

CPANdependenciesglossaryCPAN River Fri 25 September 2015

Following on from my previous post on CPAN terminology, this one focusses on the model and terminology related to dependencies: the modules that your dist uses, and the other CPAN distributions that use yours.

This post might seem a bit rough around the edges, because I've been writing it to clarify my understanding, and filling in gaps as I go. Let me know if I've got anything wrong or unclear, or missed anything you think fits here.

Module dependencies

Let's look at the module Web::Query, which gives you a jQuery-like interface for processing a web page. It uses List::MoreUtils, which in turn uses Exporter::Tiny:

part of Web::Query's upriver

This might seem obvious, but those are modules.

Distribution dependencies

You don't install modules though, you install the latest release of the distribution that contains the module. So when you type

# cpan Web::Query

you end up installing the Web-Query distribution. At the time I'm writing this, you'd install the 0.32 release of Web-Query, which is the tarball Web-Query-0.32.tar.gz

We started off talking about three modules, but now we're dealing with the distributions, all of which contain other modules:

distribution oriented view of dependencies

Here the three modules we're talking about happen to be the main modules of their respective distributions. But this isn't always the case: if List::MoreUtils used Exporter::Shiny instead of Exporter::Tiny, then obviously that wouldn't be true (see, for example, Term::Vspark).

Upstream and downstream dependencies

Most of the time when people are talking about CPAN dependencies, they're talking about distribution dependencies. If we consider the three distributions above in the context of the river model, then here's roughly where they fit:

rough positions of the three distributions on the CPAN River

Exporter-Tiny and List-MoreUtils are both a long way up the river — they're used by a lot of other CPAN distributions. The usage count includes indirect usage: Web-Query uses Exporter-Tiny indirectly.

From the perspective of List-MoreUtils, Exporter-Tiny is upstream, and Web-Query is downstream. So for your distribution, upstream dependencies are the distributions that you use, and downstream dependencies are the ones using your dist.

Classifying the dependencies

So far we've been talking about runtime dependencies: every time your code uses List::MoreUtils, it uses Exporter::Tiny. This is called the runtime phase, and there are other phases that can have dependencies associated with them. The List-MoreUtils has a Makefile.PL, so if you were installing it manually, you'd run:

perl Makefile.PL
make test
make install

With that in mind, these are the other phases:

In addition to phase, dependencies also have a relationship type, which in most cases specifies how hard the dependency is:

So now we can look at a more complete view of the upstream dependencies for List-MoreUtils, considering the modules used:

dependencies for List-MoreUtils

I didn't list all of the develop/requires dependencies. You can see that Test::More is required to run the test suite, but Test::LeakTrace is optional.

The official spec for dependency definitions is CPAN::Meta::Spec.

Core dependencies

One fuzzy area when specifying dependencies is core modules.

The main reason for specifying your dependencies is so that when a CPAN client is installing your distribution, it can check whether the dependencies are already installed, and if not, install them first.

But by definition, core modules will already have been installed.

As a result, some people list core module dependencies and some people don't. For example, List::MoreUtils uses strict and warnings, but they're not listed as formal prerequisites.

Personally I think you should list all prereqs:

comments powered by Disqus