Reviews by Aristotle Pagaltzis


Catalyst-Plugin-Params-Demoronize (1.14)

[obsolete review removed]

P (1.1.18) *

[Balancing out author’s self-submitted rating.]

AAAAAAAAA (1.01) *****

It’s stupid, but even after all this time, every time I see it, it cracks me up. I don’t know why, but it does.

Flexible-Output-Printer (0.4.5) *

Same stupid nonsense as Ez::Printer, now enhanced with extra stupid.

Flexible-Scripting-Tools (0.03.4) *

Contains only a Testing::Values::Boolean module that contains all of the same code from the separate Testing::Values::Boolean distribution uploaded within the same 24 hours, except here the code is commented out (comment: “I will never use this again”), and other useless code (such as a “donothing” function that, true enough, does nothing) added.

No code (I mean, let’s call a spade a spade here). No documentation for the no code. Stupid name.

Word of advice: if you decide within 24 hours that you are never going to use some code again, then next time you decide to upload something to CPAN, give yourself 72 hours to think that over.

Boolean-Testing-TrueFalse ( *

Identical to Testing-Values-Boolean. I’ll just quote the code here:

sub True { return 0; }

And if we pretend for a moment that someone exists who needs this nonsense, they won’t find it under this name.

Silly code, silly name, no documentation.

Testing-Values-Boolean (1.2.6) *

I’ll just quote the code here:

sub True { return 0; }

And if we pretend for a moment that someone exists who needs this nonsense, they won’t find it under this name.

Silly code, silly name, no documentation.

constant-defer (2) ****

This is a fine module. It has one caveat that the author understands, but doesn’t call out in the documentation: unlike real constants, the deferred constants produced by this module won’t be inlined in any code that is compiled before the deferred calculation has been triggered. So depending on why you are using constants instead of other mechanisms like read-only variables, this module may or may not be of use to you. This is a fundamental caveat; it is not possible to resolve without special support in the compiler and op tree.

(As for Burak Gürsoy’s negative review, please ignore. He criticises that this module injects weird subs – in Perl, all constants are subs of a particular form (cf. the source of He also criticises the use of goto – in Perl, goto has several forms, one of which provides an explicit tail call, which form is quite commonly used, particularly in all sorts of meta-programming. I found nothing surprising or unusual in my reading of the module’s source.)

Gtk-Perl (0.7009) *

Don’t bother with this distribution. (Don’t bother reviewing it either.) It contains unfinished Perl bindings for an obsolete GUI toolkit whose last release was almost 8 years ago. (gtk+ 1.2.10, April 2001)

If you think you want this module, you are actually looking for the project which has produced bindings to the current universe of GNOME libraries with gtk+ 2.x at the centre. The project’s products are available from CPAN as the GLib and Gtk2 distributions (along with ExtUtils::Depends and ::PkgConfig), plus a plethora of additional bindings such as Gnome2, Gtk2::GladeXML, Gnome2::GConf, Cairo, GStreamer and Gtk2::WebKit.

These aren’t the droids you are looking for. Move along… move along.

XML-Atom-SimpleFeed (0.82)

[This is a reply from the author to Darren Kulp’s review:]

CPAN Ratings is not the place for bug reports. What XML::Atom::SimpleFeed actually does is it encodes all input strings to ASCII, using’s HTMLCREF fallback. Effectively it will spit out all characters > 127 as numeric character references. If that ends up producing PERLQQ rather than HTMLCREF escaping for you, then your is either old or broken. Please file an RT ticket so we can figure this out.

XML-Simple (2.18) ***

Shlomi’s criticism is spot-on in several ways, though I wouldn’t go so far as to rate this module a single star. Of the problems he noted, at least inconsistent mapping to Perl data structures and inept handling of mixed content are in fact troublesome.

With sufficient experience or study of the documentation you can configure the module so that it will produce data structures that do not surprise you (or your code!), but then either the module interface or the resultant data structures can no longer be considered “simple.” If you do the simplest possible thing that can give you consistent data structures, then you will have to deal with an extra level of indirection in your Perl data structure for every level of nesting in the XML. If you want to have more convenient Perl data structures than that, you need to spend quite some time until you have XML::Simple configured *just so* for the XML vocabulary in question.

Shlomi is further correct that mixed content is what XML is all about. If your data is so regular that it can be mapped directly to a data structure, then JSON or the Config::General format or something of the sort are all much better options than XML.

All that said, this module is very useful for one-off data diving jobs. When you run into a pile of XML and you merely want to get in, pull something out of it, and get out, and never do it again, this module is quite likely to be the fastest road to success. You will often not even have to care about any botched mixed content, so in that kind of situation that is not a problem either.

But before you start building elaborate setups of XML::Simple configuration options to make your data structure map less painfully to Perl data structures, you should instead invest your time into learning XPath, for which you will be richly rewarded in convenience. Surfing an XML document with XPath expressions is much more concise than navigating a Perl data structure derived from the same XML document, particularly if you want to deal with sets of leaf nodes under sets of parent elements. That is the simplest case in XPath and will simply return a list of all the leaf nodes. In Perl, you need to nest another loop for every level at which you deal with a set.

Overall, 3 stars from me. It does what it says on the tin, and sometimes it’s just what you need, but it’s of limited use and the API has grown astonishingly complex in trying to be all things to all people.

Carp-Always (0.09) *****

I love this and use it lots. Being able to decide whether I want stack traces on exceptions on a per-script-invocation basis is much more useful than having to decide whether to produce a stack trace on a per-exception-site basis. It’s excellent for printf debugging people like me: instead of having to meddle with the code, just rerun it under Carp::Always and you get a stack trace. For many simple bugs, this already provides enough information to find and fix them.

Four thumbs up!

PS.: Please disregard Robert Rothenberg’s review; he does not appear to have understood the docs. The difference between loading Carp with the `verbose` import option and Carp::Always is that Carp::Always will generate stack traces from plain `die`s and `warn`s, whereas the `verbose` import option to Carp only enables them for `croak`s and `carp`s. The fact that Carp does not need to change die/warn handlers is therefore not an advantage, but a missing feature – nor is it usually relevant, because Carp::Always is intended for loading from outside the script (via PERL5LIB or perl’s -M switch), not as part of the regular operation of code. (It does mean that sometimes Carp::Always won’t work as advertised, but with the means provided by Perl, this cannot be helped.)

Nothing-Tiny (1)

Re: “Your opinion on this module doesn’t matter to me, so why bother writing it?”

Writing a response is a weird way of expressing your lack of interest.

Re: “Why are you wasting your time reviewing this module? Do you really have that much free time?”

Why did you waste your time writing this module and putting it on CPAN? Do you really have that much free time?

CGI-Prototype (0.9053) **

I started with CGI::Prototype on a project I still develop. I would not pick it again. I loved it at the time, but I have been looking to move away from it for a while. Back then it was the right choice: Catalyst wasn’t very well known nor very good yet, Jifty didn’t even exist, and even CGI::Application didn’t have ::Dispatch.

But CGIP just does too little and what it does do is mostly useless. Overall, it is is very “stargate oriented”[1].

• Its core idea is the “stay on this page or go to another?” mechanism. This is directly in opposition to POST-redirect-GET – and therefore to good HTTP style. I didn’t have to fight CGIP to do things properly, but I had to ignore its offerings and manually devise everything I needed.

• It is strongly targetted at classic process-per-request CGI environments. It tries to avoid compiling too much by implicitly require-ing subclasses in the dispatcher, and stores request-specific data in slots of the main object, which are effectively global variables.

• Because the dispatcher plays double duty as an on-demand code loader, it’s hard to make it do URI-based dispatching sensibly. I’ve had to reinvent lots of the dispatching infrastructure that any more comprehensive framework would have given me for free, and my code is still less flexible than the routing provided by every other framework.

• It treats the output – both the response headers and the body – as a single thing. That means you have to generate all output at once, or else you have to reinvent the mechanisms other frameworks provide to independently set headers and produce the response body – and indeed I ended up doing the latter.

• It does nothing to help you decouple concerns. Normally, no variables are passed to your templates except self, whereby your templates call back into the application. This turned out to be a very bad idea. What should have been there is a mechanism like the stash in Catalyst, which lets you prepare data piecemeal in the controller, which is finally passed to the template. This too – you guessed it – I had to write myself.

Overall, between ignoring its suggested ways of doing things, overriding its defaults, and writing infrastructure myself, I basically wrote my own web framework on top of the tiniest bits of CGIP.

[This review was also posted on my use.Perl journal. [2] See there for discussion.]


Class-Accessor-Classy (v0.9.0)

[Retracted negative review; the criticised lack of user-level docs has been addressed.]

Moose-Tiny (0.0.1) *

Not ::Tiny at all and fails at being either practical or funny.

DBIx-Simple (1.31) *****

A beautiful piece of work indeed.

Initially, I purposely avoided using any helper or abstractor modules on top of DBI, because I wanted to see what real problems I would encounter with its use – if any. After a couple of projects with it under my belt, the main problem that stuck out was that I was going crosseyed at all the (select|fetch)(all|row|col)_(array|hash)(ref)? methods in my code (some of them *additionally* modulated by passing an empty hash to indicate that I want an AoH rather than an AoA). What data structure would any piece of my code return? I could never tell at a glance, so I was fighting an increasingly uncomfortable feeling of programming by coincidence. I had lost my confidence and kept getting jarred out of the flow, so my productivity was taking a substantial hit.

So I struck out to find what DBIx::* modules from the CPAN might be applicable, and to evaluate how well they’d address this particular need of mine.

Most of the modules that made it into my first broad selection have a very different focus. Closest among the differently-focussed modules are DBIx::DWIW and DBIx::Easy, which were in the race until the penultimate round. Those mainly allow you to avoid some of the more menial SQL labouring, but they come up short in terms of options for simplified fetching of results. Since I already have a lot of SQL queries written, and because the things I ask of my databases are usually not complicated, but still non-trivial, I did not stand to gain much from the major offerings of these modules.

Thus, the last two modules standing were DBIx::ContextualFetch and DBIx::Simple. In this shootout, DBIx::ContextualFetch clearly loses. It does not address fetching results as flattened structures at all, and all of its handful of methods have quite similar names, much like in DBI. Its main aim seems to be to keep with DBI tradition. In contrast, DBIx::Simple offers methods for pulling out query results in every possible data structure you might prefer, and the methods are named distinctly and memorably, with a natural and consistent scheme for distinguishing between fetching only one row or all of them. It is exactly what I need.

It’s additionally nice for integrating SQL::Abstract, SQL::Interp, DBIx::XHTML_Table and Text::Table smoothly, without putting any pressure on the user to buy into these modules. I have found the SQL::Interp integration very natural; and while I have no need for DBIx::XHTML_Table or Text::Table right now, the integration offers a very easy growth vector. That’s all quite cool, and reflects the same virtues as Perl itself or other great modules like the Template Toolkit. (But I avoid SQL::Abstract because of limitations in the SQL constructs it can express and because I find complex queries written in its datastructure-as-language style very hard to read.)

This is one excellent module: simple and focused on a particular purpose which it fulfills perfectly. I recommend it without any reservation.

Net-Lite-XMPP (0.01) *

No code, no docs, no tests. Useless.

CGI-Ajax (0.701) **

This module is nice for quick and dirty stuff if you’d prefer not to learn anything about Javascript. It’s not very suitable for serious use, though.

It builds a bunch of Javascript for inclusion in your HTML, so you won’t benefit from caching. The documentation encourages the use of onClick attributes in the markup, rather than unobtrusive scripting. It turns Ajax into RPC that won’t easily play well with frameworks and disregards the fact that there’s HTTP in the middle (you can’t use methods other than GET and POST or set any headers, eg. use conditional requests). The code is tightly coupled with (which, admittedly, is a benefit in quick’n’dirty scenarios).

In short, CGI::Ajax gives you the worst in webapps as of 2006 combined with the worst in webapps as of 1996.[1]

If you are serious and need to build more than a tinkertoy of an Ajax app (which, admittedly, not all of us need to), I would suggest to instead acquaint yourself with the following things:

a) the meaning of “unobtrusive Javascript” (see Wikipedia for a very short overview)
b) jQuery (a Javascript library, see
c) ETags and conditional requests (beyond just their use for caching)

That will give you the tools necessary to build Ajax apps that scale up nicely – with code size, in maintainability; and with your audience, in performance.

Of course, that won’t scale *down* as nicely. If you just want to slap together a page with a few buttons to change state on the server (you’re doing home automation and have put your coffee maker on an X10 wire, say), then CGI::Ajax will allow you to get that done with the minimum effort possible.


[1] Exaggerated for pithiness, I’ll admit. It could certainly be much worse than it is. :)

ack (1.58) ****

This is a great tool. It’s not going to replace grep anytime soon, but for the subset of grep tasks that developers commonly need, it’s extremely convenient.

However, I really, *really* miss the --exclude and --include options from grep. My projects often contain directories with large files containing code that aren’t actually code I’m writing, such as database dumps or compressed Javascript libraries, which clutter the results. It’s possible to kludge around the problem a lot of the time by using options such as --nojs and/or --nosql. But when I want to search the database schema files that *are* part of my own code, or I want to search in my own Javascript sources, then I’m left with some awkward `find -some -predicates -type f -print0 | xargs -r0 ack` construction – which is much worse than the grep equivalent.

So that’s my verdict: this is already a tool every developer should have. And if it had --exclude/--include, it would be *perfect*.

Thanks, Andy.

XML-Tiny (1.02) *

This is silly. The module ignores important aspects of XML; if you use it, and you do not control the code on the other end of the wire that generates the “XML” which you want to process with XML::Tiny, you are on your own. It may work now, but you have no idea when the other party might change their code to use legal aspects of XML that this module will choke on.

Furthermore, it will fail to reject many documents that are not valid XML, so the language it implements is not a proper subset of XML.

Additionally, the author’s design choice to unescape a select few entities (most importantly &) but no others means that any text content you retrieve from this module is mangled so that it is impossible to recover the original text faithfully.

If you want to process XML, but you can only install pure-Perl modules and you want to avoid the hassle of a large dependency tree, then I recommend that you use XML::Parser::Lite instead. That is a single Perl-only module whose author elected to invest his time in the implementation of a complete XML parser rather than into docs justifying his code’s brokenness and complaining about the XML police’s detachment from reality.

Since this module already has users, the best strategy for the future would probably be to re-implement the XML::Tiny interface in terms of XML::Parser::Lite as well as such is possible (but breaking compatibility where necessary for correctness), and then make XML::Tiny a stub module in the XML::Parser::Lite distribution.

Acme-VerySign (1.00) *****

One of the funniest Acme:: modules on CPAN – truly a worthy addition to the namespace. Kudos to Mark for the excellent parody-fu.

Class-InsideOut (1.02) *****

This module is an excellent implementation of the concept and in fact the only one on CPAN that I consider acceptable.

Adam Kennedy writes that “the number of uses in which is has a positive effect large enough to make up for its negatives being exceedingly small.” I disagree. The traditional way of doing OO in Perl 5 is curiously stuck in an era where namespaces and do not exist, much as they did not in Perl 4. As Class::InsideOut::Manual::About outlines, inside-out objects enjoy the “vars” stricture for the names of instance attributes and a natural way to namespace the attributes so that sub- and superclasses can define identically named attributes without treading on each other. And because the referee is not even used, it can be of any type, making classes truly modular and independent of each other.

It is a common misconception that inside-out objects are mainly about strong encapsulation. In fact, that is only a minor point of the technique, and one I would encourage people to give up by using “our” instead of “my” for their property hashes. If you are after true strong encapsulation in Perl 5, you should use closure-based objects; it is close to impossible to breach that protection.

The benefits lie elsewhere, and Class::InsideOut is the only implementation on CPAN to provide them in full. Not only does it do so, it does it with an elegant and minimal API that is well documented. I have no complaints whatsoever.

Chest (0.082) *

This is a trivial OO wrapper implementing the concept called a dispatch table (ie. subrefs in a hash). All of its methods are direct equivalents to a single statement manipulation of a hash, so it hides the intent of trivial code behind an API. You don’t get any added simplicity for that obscurity, but you do get an extra dependency.

The module name is horribly chosen: I certainly wouldn’t think to use “chest” as a keyword when searching CPAN for something like this – assuming I ever felt the need for an OO dispatch table in the first place. It also opens a new top-level namespace… why it needed to, I’m not sure.

At least it has decent docs and a superficial few actual tests.

To make an unnecessarily long story short: stay away.

Carp-Clan (5.3) *****

Before I discovered this module, I would play silly games with “local $Carp::CarpLevel = $Carp::CarpLevel + 1” sprinkled all over the place. Not only was that annoying, it also hatefully causes Carp to emit verbose messages. Now I just use Carp::Clan and things work as I meant them to.

Of course, that’s not the module’s only use – but that alone makes the module worthwhile to use everywhere, even if you don’t have a “clan” of modules.

My only question is: why is this not part of the core? Why indeed doesn’t Carp itself work that way?

YAML (0.58) *

I just wanted to echo Adam’s sentiments here. Let’s put it this way: the YAML spec is a good deal more complex than XML 1.0. ’nuff said.

In addition, 0.58 depends on Test::Base, which in turn depends on Spiffy, which in turn makes me really uncomfortable.

Someone should take the most important 10% of YAML’s syntax and make a spec out of that. It would be brilliant.

Bencode (1.0)

Some notes on this module from me as the author:

Originally I had no plans to release this code. I just wanted a script to read .torrent files, which I tried to write using Convert::Bencode and Convert::Bencode_XS. Neither of them worked on any of the files I tried to read. So I ended up rolling my own, and while I only intended to implement the minimum I needed, I found that the bencode format is so simple that writing a partial implementation is not even possible.

So now there was one working bencode implementation in my script, and none on CPAN. Why not upload the code? And that’s what I did. I poached the unit tests from the original, made them all pass, and then wrapped it into a package and dropped it in CPAN’s lap.

The other issue concerns the name. I had pondered which namespace to place this module in. The Convert:: namespace seemed ill-thoughout. Bencode is a data structure serialisation format. Historically, serialisers in Perl are generally in the toplevel namespace: Storable, FreezeThaw, YAML. So I opted for the same route. I did consider Data::Bencode (along the lines of Data::Dumper) and may yet rename the module.

But that’s that for now.

Share and enjoy.

Acme-Pasty (0.01) *

Ditto Smylers. I think this warrants admin intervention.

File-Find-Rule (0.30) *****

Excellent idea with an excellent execution, excellently documented. Directory traversal code using File::Find::Rule documents intent far more clearly that equivalent File::Find callback code ever could. And true to “easy things should be easy,” code for the simplest use (accumulate matches in an array) is trivial.

Gtk2 (1.140) *****

Absolutely excellent bindings for the best GUI toolkit out there. Easy things are usually easy, and hard things are possible and occasionally even easy. The bindings are completely perlish, and the underlying class library is cleanly designed. Unlike Tk apps, Gtk2 apps will not offend your eyes – neither when running them nor when looking at the source.

If you’re writing GUI apps in Perl, this is what you should use.

Text-MicroMason (1.992) **

I really, really wanted to like this module. The documentation is great, the interface is bliss, the Mason syntax is cool, and having multiple syntaxes is excellent.

Unfortunately, my experience was so painful that I gave up after a day of using it. Maybe it would have been different if I had come to it with a blank slate, but that is not my situation: I am currently getting increasingly fed up with Template Toolkit’s crippled mini language (a rant for another day), so I was looking for a different system that would let me use Perl in my templates.

I have a batch of templates that need to be ported – but that has proven absolutely impossible. The error reporting is so indescribably abysmal that the excercise turned out worse than pulling teeth. Some errors segfaulted perl! I have no idea what the precise problem was, I gave up much before I could triangulate its exact location in the template. And triangulate I had to: simple template syntax errors result in nothing but an error on the line in your own code which invokes the compiled template; grave errors produce an enigmatic error from deep in the bowels of the module. If you’re lucky, there’s a dump of generated, hard to read Perl code from which you can try to decipher the problem. If you’re particularly unlucky, you get a segfault.

Now, I’m possibly an outlier. It’s quite conceivable that these problems are far less of an issue when you’re starting from scratch with an empty file, instead of trying to port an existing template from one syntax to another by applying incremental search-and-replace patches and then running the result to see what breaks. But this experience still makes me wary for maintenance programmers who come in months after the fact to tweak a template.

Gtk-HandyCList (0.031) *

Do not use. This module is deprecated.

(Note: I am its maintainer. I shepherd it for the poor souls who still need it.)

Roll (1.0) *

The only change from the h2xs module boilerplate is the author’s name and a sentence in the README. There is not even any code. Why anyone would want this module I don’t know.

Even if it was what the README says it should be, the name would be badly chosen. It should be somewhere in Games:: then.

Acme-DRM (0.01) ****

Everyone should use this! Protect your Intellectual Poverty today! How are you going to be Creative if you can’t make money with your ideas?

I would feel more comfortable if the source code was itself encrypted, though, so that the module’s customers cannot tamper with it. Please correct this in the next version!

I am slilghtly wary because I can’t find a way to purchase a licence from the author either. Doesn’t he believe in the soundness of his ideas? Why would he give away a brillant piece of engineering?

HTML-Tag (0.01) *

No documentation whatsoever.

No strict, no warnings. Gratuitous use of eval().

It generates XHTML-style empty tags, but uses uppercase tag names – and XML is case sensitive.

It scores at least a few points for having a test suite at all, although it’s so basic I doubt it’ll ever catch any bugs. Some of the tests rely on Tie::IxHash, which is not listed as a dependency.

Neither is Class::Builder, although the module itself relies on that.

In its current state, I can’t recommend its use to anyone.

Assuming all the problems were corrected, there’s still the question as to why one would use this module over the many very similar but more established and mature modules.

Package-Constants (0.01) ***

Overall, nice module and documentation.

The gratuitous use of method call syntax for the list function grates on my sensitivities, though.

Also, since it identifies constants only by their prototype, it will incorrectly identify any parameterless function as a constant. An airtight detection routine could be written using a B module. In practice, this will be rare, so a mention of the issue in the BUGS section could also suffice.

XML-Genx (0.17) *****

If you need to fling XML down the wire, this is for you: the API is simple and intuitive, the generated XML is sanity-checked, and the speed is what you’d expect from C code.

Good stuff.

HTML-Perlinfo (1.00) *

This module is a can opener inside the can. If you can install it, you already have the most important information that it can provide you, particularly as it depends on multiple non-core modules.

There’s a lot of additional information that seems to have been added purely to make an impressive display.

The code is an excercise in bouncing on the copy-paste key. Presumably to reduce the effect of having to cope with that, the code is broken up following the form of packages, but it does not actually use packages, and none of it is reusable.

The choice of namespace is really poor. There is precious little HTML-specific about the purpose of this module.

Sudoku (0.02) **

I’m reviewing this mainly to complain about two things.

First is that I’m puzzled as to why the distribution is called Sudoku, when the modules are in the proper Games::Sudoku namespace.

Second is that most of the documentation is just the unmodified default templates from h2xs (README, Changes etc), including “blah blah blah��? bits. Only the main POD actually has any content – with the text formatted as code and the code formatted as text…

Log-Log4perl (1.06) *****

This module is a flexible framework that deserves the name: it does not unduly impose any particular style of use on you, and makes it very easy to do trivial things. The API scales easily and seamlessly from 10-liners to 100,000 LOC projects.

An indispensable tool.

File-DirWalk (0.2) **

In addition to the issues in Robert’s review, it’s also missing any useful tests.

Note that any remotely recent version of File::Find actually does offer extra hooks for entering and leaving directories etc. The bottom line is that using this module will add a dependency to your code without providing anything not otherwise doable – not even a better interface.

A quick glance reveals that it at least doesn’t run afoul of the classic directory recursing trap, looping infinitely in circularly symlinked trees.

IO-All (0.35) *

It gives me the heebiejeebies. The first line in the synopsis reads “Let the madness begin…” and this review could really end there, because that is exactly what I have to say.

But that wouldn’t be a very helpful review, so I’ll say what’s wrong with it. The problem is that there is way too much overloading going on. Just about every operator means something else when used on an IO::All instance as on any other variable in Perl. The meaning of filenames is also overloaded; the result of the code “io( "localhost:80" )” depends on whether a file called “localhost:80” exists in the current directory, or not. All of this certainly helps brevity, but ask yourself: are you writing production code or competing in an obfuscation contest?

The issue this module tries to address – writing I/O code is awkward and often too verbose – is real, but sorry: this is not the way to go about it.

CGI-okTemplate (0.03) *

Do we really need yet another templating system on CPAN? From the looks of it, it's a simplistic engine roughly on par with CGI::FastTemplate.

Note that it uses the $` and $' variables, so just loading this module is going to impose a performance penalty on the rest of your code wherever you use a regex.

If you think you want to use, you should probably pick one of the more widely used templating systems instead. If you need help deciding, read Perrin's templating system comparison article:

Acme-Raise_my_kwalitee (0.02) *

This is an abomination. Please remove it from CPAN.

POSIX-strptime (0.05) *****

It's unfathomable to me why bindings for strptime() are not included in the core POSIX module that comes with Perl. This module delivers the missing part. Very handy for no-frills date parsing in situations where all you want is to accurately convert formats.

Convert-Binary-C (0.58) *****

I'm just chiming in to agree with Tassilo's review. This is a great module.

Module-Pluggable (2.7) *****

Very nice. Simple, Perlish, well documented, works well, provides sensible defaults while catering to particular desires. There's nothing to complain about.

CGI-GuruMeditation (0.05) **

This doesn't seem to offer anything which CGI::Carp doesn't already do. All it adds is a builtin HTML error screen (with excessively verbosely written CSS) that might be seen as a little more pleasing than what CGI::Carp spits out. Or might not; it includes Javascript to blink the error message, true to the module's name. And it contains an incantation which attempts to extract an excerpt of the source location where the error was thrown. Extraction relies on $0 so the code will show the wrong thing if the error was thrown inside a module rather than the main CGI script. The author includes his very own HTML-escaping function, whimsically nested into the module's main function.

I admit it's kind of fun; but that's this thing's only real saving grace.

String-Charcount (0.11) *

Is this some kind of joke? The author appears to be unaware that there's a tr/// function in Perl which does just what this module is supposed to. Only the count_unique() function requires any sort of effort to replicate, but there are more efficient ways to do that than this module's implementation.

CGI-Session (3.95) ****

Very nice job. Intuitive interface, does what you want, and caters to slightly less trivial needs just fine.

The only gripe I have is that it stores serialized Perl structures as opaque text/BLOB fields rather than even attempting to store the data relationally, but that limitation also means it is very easy to get working and that it can store any data structure Perl can handle. So there is definitely a trade-off involved.

Text-Rhombus (0.15) **

An implementation of a single trivial and mostly useless function. The code quality is rather middling too. Probably belongs in Acme::.

AZ-Splitter (0.60) **

A stream tokenizer with an awkward interface and a horrible module name.

The only upside is that it comes with pretty thorough documentation.

DBD-SQLite (1.08) *****

I have nothing but praise for SQLite and DBD::SQLite. With this duo, you are suddenly free to use a relational datastore for each, every and any script, however trivial, without all the overhead associated with administrating and managing a database server that would usually keep you from doing so.

SQLite is not the best choice for applications with high demand for scalability and concurrency where a traditional database engine can keep up significantly better; but really, that goes without saying and is beside the point.

Ctype (0.01) *

It is unclear why this module is necessary. All of the tests it provides can be realized by a pattern match using POSIX character classes, so this module's isxdigit() function (as an example) can be replaced by matching against /[[:xdigit:]]/. For upper- and lowercasing, Perl has builtin functions which are much shorter to type. In other words, there is nothing here which plain Perl doesn't already do.

Class-HPLOO (0.23) *

This module is confused. It doesn't really know what it wants to be. Source filter for extra OO syntax? Filter for implementing subroutine signatures? Foreign language inlining? HTML templating? HTML inlining? Go on, you'll find a little bit of everything.

That is, if you do, since the documentation struggles to list all of the features, without managing to even attempt a coherent explanation of why and how all the features should be used. Not surprisingly for such a formless amalgamation of unrelated concepts, the module's name is meaningless.

If you think you need this module, you should probably be looking at Perl 6 instead.

SQL-Abstract (1.18) ****

This module is absolutely great if your needs in terms of SQL complexity are simple. It Just Works the way a Perl programmer would expect. You can be up and running in very little time; for small scripts automating simple tasks it's just what the doctor ordered.

Unfortunately, things start breaking apart if your needs are more complex. The resulting structures can be hard to visually parse and grok. There is no provision for subselects either, regardless of effort invested; it's just not possible to do them in its current state.

The documentation is generally well-written and helpful. It could be a little better organized (I often found myself spending too much time looking up things), but that is a somewhat minor quibble. Everything you need to know is in there somewhere.

I'd rate this module between 3 and 4 if it was possible, but it has definite potential to earn a 5.

XML-LibXML (1.58) *****

I'll start with the bad: the documentation is complete, but very sparse. It lists most everything you need from the module, but it explains very little.

This does have a negative effect on ease of use at first; but really, it's only a matter of experience and third party documentation before you overcome the hurdle.

The interface as such is lovely: a pretty straight but still comfortably Perlish translation of the C API of the underlying library.

And of course, libxml2 just plain rocks.

Overall, ever since I figured this module out, I haven't wanted to use anything else for my XML manipulation needs.

perl (5.8.6) *****

This rating is just symbolic. :-)

In actual fact, I don't believe Perl deserves 5 stars on all counts (documentation, interface, ease of use); it doesn't even really deserve them in any one count. (To be sure, none of them deserves less than 3 stars either.) But it is a big distribution, with *many* separate things to review. A lot more than three criteria would be required to even attempt a real review, and they'd need a finer scale than 1-5 stars too, and a review wouldn't fit in this margin anyway.

So I give it 5 stars for the great things it has accomplished and continues to accomplish, rather than for what it is, and I think that is perfectly justified.

Comma (0.03) ***

Unlike Robert Rothenberg, I can see the value in the module's use of a tied hash interface: namely, you can interpolate a call in a string. (Maybe Robert should have read the "SEE ALSO" section.)

I don't know why we need a module that is nothing but a specialization of though.

However, my real beef is with the name. Both "Comma" and its new name "Tie::Comma" are useless: without a look at the documentation I couldn't even begin to guess what this module is supposed to be for.

Time-Out (0.05) ****

A great module.

The reason I give it only 4 stars is the frivolous 'affects' syntax. It looks like it adds semantics, but it's actually a no-op. You can (and should) just say “timeout $x => sub { ... }” to make this clear.

Other than that, I have no complaints: the interface is natural, the docs are as exhaustive as such a trivial interface requires, and ease of use… well, it would be hard to make this difficult to use.

Text-VimColor (0.08) *****

Absolutely terrific.

Well documented, with a clean interface, easy to use, and does exactly what you expect, reliably.

DBD-mysql-SimpleMySQL (0.5) *

An SQL abstraction layer that’s uglier than writing SQL.

I’m not sure we need another one of those anyway, but working on the assumption that someone does want this, I find fault with its execution in the following ways.

As far as the documentation allows a call, the API seems limited. I’m not sure it gives you full access to the power of SQL. Unfortunately, that cost does not come in exchange for clarity and simplicity: the interface is less than intuitive.

The documentation is rather unhelpful. It consists of two examples and a monosyllabic description of each function in the module. The examples are neither self-explanatory nor commented – I can only guess what the code shown is supposed to do. An overview of the mechanics of the module or some description of the model of operation assumed is missing entirely.

The choice of namespace is the single worst aspect of the module: it’s a database access wrapper rather than a database driver, so it belongs in DBIx:: instead of DBD::. I can’t see anything that makes it particularly MySQL-specific, either, it looks fairly database agnostic.

By the time time you figure out this module, you’ll probably be well equipped to write something equivalent more suited to your own habits yourself. In its current form, it’s not likely to be useful to anyone other than its author.

SuperPython (0.91) ***

This was definitely worth a chuckle.

I don’t think it should be under Acme:: – that would spoil the point. Misleading POD? No, it isn’t. Intentionally incomplete POD? Of course – it *has* to be.

It gets a 3 from me because it certainly doesn’t deserve 5 stars as it’s not useful for any practical purpose. OTOH, I don’t think it’s actually bad for this to be on CPAN, so I’m not rating it 1 or 2 either.

Sort-Flat (0.18) *

In its current implementation, this module is worse than worthless. It solves an exceedingly trivial problem with an excessively brutal tool and pays no mind to concerns of flexibility and user choice.

It is understandable that someone who wants to do a lot of case insensitive sorts might want a less awkward way to specify this, than by spelling it out explicitly every single time. Unfortunately, the sort() builtin doesn't have a prototype custom Perl code can emulate.

So this module runs a source filter on the code to drop a case insensitive comparison block on all block-less sort calls.

This makes it useless in production environments, because source filters may break code in subtle ways and conceil what the Perl compiler actually sees from the programmer.

There is also no direct way to exclude specific calls from this module's treatmeant, only awkwardly, by adding a { $a cmp $b } block yourself. Fortunately, recentish Perls will recognize its do-nothing-extra nature and do a straight, blockless call -- but this wasn't always the case.

Why not simply export a sorti() routine into the user's namespace? The added verbosity of one character can't be a serious problem; personally I would even consider it desirable, to remind a later reader of the code that this isn't your standard sort happening here. It can't really matter that you can't tell whether a coderef passed in $_[0] was meant as a sort function or was part of the data to be sorted, either -- if someone is using a sort function, they already have a block, so they can just call the normal sort() and put in case insensitivity themselves.

The only reason I could at all think of is that it adds an extra function call, which might rub a microoptimizing programmer the wrong way -- but then just exporting an nc() function (for "no case") to be used as in "sort nc @list" would solve that problem. Also, the sort function used here doesn't cache the transformed strings it compares, which is likely to cost a lot more cycles than the intermediate function call and return value copying if a lot of data is being sorted. If performance is really the goal, there are better choices:

* One would be to use a B:: module to modify the optree, which, much like the source filter, modifies the code before it is executed, except that it's not nearly as easy to break as source filters. Of course, it's also much harder to write such a beast.
* The other would be to write some XS, which I'd prefer -- it's then possible to transform the strings being compared as they are being compared, character by character, so the transformation can be aborted as soon as the first difference between strings is found. In many cases, this means only the first character is at all transformed.

My final gripe is with the name. Sort::Flat makes me think it tries to solve some issue relating to nested data structures. In fact, I checked it out when it appeared in the Recent Uploads list *twice* so far, forgetting what it was about after the first time, because I wanted to see what "flat sorting" meant. A much better name would have been something along the lines of Sort::NoCase.

At least the documentation is more than ample and takes the time to describe the module thoroughly. :)