Reviews by Joe Brenner


Perl-Staff (0.03) *

There's certainly precedent for non-code cpan releases (e.g. all the Cookbooks), but that doesn't mean that this one isn't an "abuse" of cpan. It would make more sense to put it up on the perl5 wiki, for example. It would also make more sense if the name specified what it actually was, e.g. "Perl::Events::Staff". I'm sure the people whose names are listed here are doing good and useful things, but they're not the first people I would think of as the "Perl::Staff".

Encode (2.39) *

Once again, this is a review of "Encode::Guess", not "Encode" (cpanratings needs work).

Encode::Guess is one scary module... in my first trial with it, I asked it to distinguish between latin-1 and utf-8, and it guessed that the latin-1 file was utf8, even though I'd intentionally put some octets in there that wouldn't be valid as utf8. Peeking at it internally, I see it's using the Encode::is_utf8 function, which the perl porters swear up and down is not at all a reliable way of identifying utf8 data (it's apparently very badly named).

What it's actually trying to do is a little difficult to understand from the documentation, and I suspect you need to know a fair amount about character encodings for it to make sense at all (e.g. there is no way for it to tell the difference between many encodings, and it's your problem to avoid giving it an ambiguous choice in the list of suspects).

Getopt-Long (2.38) ****

There are a lot of competitors out there in the Getopt::* namespace, but none I've looked at actually seem like they're worth the trouble.
Getopt::Long does around 90% of what you really need, though in my opinion the default behavior is a little unfortunate: don't ignore the "bundling" and "no_ignore_case" options. If you want some clues about The Right Way to do use Getopt::Long, take a look at Andy Lester's App::Ack... he's already thought about this harder than you and I have.

Class-Base (0.03) ****

Class::Base does the minimal amount of work needed to implement hash-based objects with a separation of creation (new) and initialization (init) -- see Conway "Object Oriented Perl", 1st ed., Chapter 6, p. 174. Class::Base objects also have a simple mechanism for logging debug messages (the debug method and the debugging setter to turn it on and off). For my applications, I also appreciated what it does not do: there is no "AUTOLOAD" facility to automatically generate accessors -- since I have my own ideas on accessor naming conventions (I don't like the "get_*" prefix: I do"set_foo"/"foo", rather than "set_foo"/"get_foo"), I wanted to write my own AUTOLOAD. Most of it's competitors get too fancy: Class::Base just does the few things I need, and lets me do what I want.

One quesiton though: what's the purpose of the (oddly named) "_ID" field inside the object? Isn't its value always the same as ref($obj)?

IPC-Cmd (0.40) *****

If you take a look at the documentation for IPC::Run or IPC::Open3, you'll see why a lot of us are overjoyed to have this sane, easily comprehensible wrapper around them that does the job of running an external command and capturing it's output for you in a simple, portable way.

I have one complaint about the interface (and I don't think it's possible to pick-up this oddity just from reading the documentation): if you do a scalar call to "run", the output buffer contains lines from stdout and stderr mixed together in chronological order. But if you do a list call, the "full_buffer" turns out to be an arrayref containing stdout and stderr as separate elements. That makes this "full_buffer" redundant with the stdout_buffer and stderr_buffer. In summary: If you want stdout and stderr intermixed, you need the a scalar context call, if you want just stdout or stderr, you need a list context call. This is a peculiar design glitch in a module who's reason for existence is it's clean interface.

List-MoreUtils (0.22) ****

I'm still discovering things to like about this module. For example "pairwise" is a nice thing to use until iterators come along:

@products = pairwise { $a * $b } @factors1, @factors2;