Discussions about module versions have touched on questions of how to distinguish or specify interfaces/APIs a few times, but I haven't seen much detail, so I thought I'd post some musings on the subject.

At its simplest, I want to add some functionality to my program by using some module; and plenty of p5 code is just that simple. But I might also want to specify a version number so I don't end up with some obsolete version of the module that won't work with my program. And higher version numbers are (in general) assumed to be better, so I don't want to limit my code to using just the module that happened to be available when I wrote it; I need to specify some range of versions, e.g. "v1.2.3 or higher", to try to catch any improvements from future releases (or just to catch the availability of later releases, in case the older version isn't installed).

S11 gives us wildcards and smart-matches to do this sort of thing: use Foo::Bar-(1.2.3..^2.0 | 2.6...). But if v1.2.3 is the cutting edge when I write my program, I don't know that v2.0 is going to throw out a bunch of deprecated methods, nor that v2.6 is going to bring them back because of overwhelming popular demand. So I have to ask myself do I feel lucky? Or am I going to update my code every time one of its modules is updated (not to mention other people who might be using my program)?

What I really want to do is specify, "I wrote this code according to version 1.3.1 of the FooBar API" and have Perl pick any module that claims to satisfy that spec. After all, the module should know what version of the API it offers. If Smith updates his Foo::Bar module, he knows whether the interface has changed and his module can say so.

Of course, I still want to be able to specify version numbers as well, so for example I can say, "use [API] FooBar-1.3.1, but don't use particular version SMITH-2.3.4" (because I happen to know that it's buggy, even though it advertises itself as filling the API I requested). In general, though, a program would ask for modules that provide the specific interface that it was written for, and expect to get the highest version available for that API.

Which version is the highest is a more complicated question when different people are writing modules for the same API. I guess if Jones writes a module that he considers better than Smith's version SMITH-2.5, Jones can just call his version JONES-2.6 (even if his previous version was only JONES-0.5).

The author[ity]'s name itself is really just part of the version, I guess (or a separate dimension of versionality -- if the version number defines the version across time, then the author represents the version across space). But the whole version number-and-name can be considered separate from the interface name. The API name should stay the same, because it doesn't change. Thus it shouldn't matter whether multiple people are writing module versions, or whether Jones takes over maintenance of Smith's module. The versions might change from Foo::Bar-SMITH-2.5 to Foo::Bar-JONES-2.6, but the API will still just be Foo::Bar, and so my code doesn't care.

Well, if there's more than one API that wants to call itself "Foo::Bar", we can add an author and call it Foo::Bar-SMITH, and it doesn't matter if Jones takes over one day. Jones's *versions* could have his name, but the API would always be Foo::Bar-SMITH because Smith invented it.

Actually, the API name can be anything, as long as it's unique. Whether it's worth defining parts like number and author (inventor?), etc. the same way we do for versions, I'm not sure. Having a well-defined structure is beneficial only if there's a use for the separate parts. (E.g. we can pull out the "number" part of a version to figure out which version is more recent than another.)

APIs would typically have some number in their name (e.g. Foo::Bar-10.3, Foo::Bar-10.4), but unlike a version number, that's not terribly useful to Perl (hm, is it?). Bigger is still probably better to someone who's writing a new program, but for code that's already written, it doesn't matter whether the API is slightly different or completely different -- you can't simply substitute one for the other. And while I would expect module writers to typically use numbers to distinguish evolving APIs, you could just as well label them Foo::Bar-Panther and Foo::Bar-Tiger if you wanted to.

Really, where I refer to 'versions' above, I should be saying 'implementation versions' as distinct from 'interface versions', but I think (for today, anyway) that we don't care much what goes in the API identifiers at all. The names don't even have to be explanatory (it works for Theorem::Pythagoras) -- we could rely on the module to supply a list of keywords to explain what it's for or to use in searching.



-David

Reply via email to