Reviews by Ricardo Signes


TheForce (0.002) **

Why not use Mouse, or (use Class::Accessor "antlers"), or use Moo, or use Mo? There are plenty of "looks like Moose, but isn't" systems already. We don't need any more unless they bring something really new to the table.

Test-Exception (0.31) ***

Test::Exception is very useful, but can be quite a bit more complicated than is clear. It uses Sub::Uplevel to hide its own place in the call stack, which is almost never necessary for testing, and can have bizarre side effects and interactions with "caller."

I suggest considering Test::Fatal, which has a much simpler API and implementation.

Class-Bind (0.2) *

I agree with the previous review: this module goes out of its way to address something that is, in Perl, a non-problem. It does it in a way that will complicate programs and seems likely to introduce bugs and confusing behavior. Just use a closure.

Sub-Uplevel (0.22) ***

There are very, very few places when you need this library. I think the only place it's really needed is when you must interact with code that you don't control, and which decides how to behave based on its caller, and you need to change the call stack. This is *extremely* rare. Almost every use of Sub::Uplevel is a mistake. It is *very* useful to have on those rare occasions when it is needed, but it would be better, whenever possible, to simply fix the other end of the problem to not require Sub::Uplevel.

Module-Install (1.00) **

I used Module::Install for quite a long time on quite a few distributions. Although it was easier to use for most things, it was hard to find out how to do new things because the documentation was scattered or missing. This would not have been too big of a problem, except the code was also quite strange, and tracking down how any particular thing worked was difficult. Writing extensions was similarly hampered by difficulty in reverse engineering or testing. These days, I stick to ExtUtils::MakeMaker and a distribution packaging system of my own design.

Sys-Hostname-Long (1.4)

This does not always do the same thing as Sys::Hostname.

~$ perl -MSys::Hostname::Long=hostname_long -le'print hostname_long'

~$ perl -MSys::Hostname -le'print hostname'


String-FriendlyID (0.011)

See also Number::RecordLocator and Number::Nary

Try-Tiny (0.02) *****

This code is both excellent and important. It will grossly simplify the way you can handle exceptions. Although it may look like nothing more than eval{}, it is handling all the edge cases that most Perl programmers don't even know about. It will prevent a large class of horrible, difficult to diagnose bugs that cause action at a distance and other forms of baffling failure.

If you are going to throw exceptions (and you probably should) then you should use Try::Tiny to handle them.

EasyDate (103) *

Previous reviews also fail to mention that the code does not actually work. The "new" method forgets that the class will be in $_[0] and thus has an off-by-one error that will make all new objects broken. In fact, the code doesn't even compile! (Bug report filed.)

UNIVERSAL-require (0.13) *

This module adds methods to UNIVERSAL. This alone is the reason you should not use it.

Class::Load now provides the same general features, but without touching UNIVERSAL, and with a few more useful options.

Email-Send (2.196) **

Email::Send is reasonable for sending off a message if your needs are very, very simple. It has numerous issues, though, and should be avoided in favor of its replacement, Email::Sender.


* you can't specify envelope (smtp/sendmail) sender/rcpts distinct from message header
* the return values are bizarre and confusing (Return::Value)
* SMTP will always send even if some recipients are refused
* "message modifiers" are called cumulatively instead of on message clones
* transports generally have no state and cannot be persistent
* the default behavior is to try every mailer available, including the Test mailer, potentially losing mail

Many of these problems can't be fixed without significant problems or backwards incompatibility. Please consider using Email::Sender (and Email::Sender::Simple) instead.

OP (0.301)

(consider this rating deleted)

Time-Local (1.1901)

Wait for Time::y2038 to be more stable, then use that. Time::Local is fine, but it has too many special cases for interpreting data.

Mail-Mbox-MessageParser (1.5000)

Saying that mbox is "just" a bunch of messages separated by lines matching /^From / indicates that the reviewer doesn't know what he's talking about. mbox is a family of incompatible formats, and coping with them is a pain. See also

The problem is that while it's easy to describe the start and end of a mbox entry, once you know where they are, it's not necessarily easy to find them. The middle of an mbox entry, unfortunately, can contain lines that look like the beginning of a new message. The differences relate to how lines that match /^From / are evaluated for whether or not they start a new message.

reform (0.3) **

I have seen the future, and it is not implemented with source filters.

Template-Toolkit (2.19) ***

TT2 is a that allowed me to turn a lot of my old, horrifying code into nice, simple code. Abstracting logic from presentation is all well and good in theory, but without a really good templating system, it just doesn't happen. TT2 was able to do everything I needed, and sometimes made me see new and better ways to break my code into little tiny pieces.

Despite that, it's got a number of big warts, including the lack of an undef value, the lack of context when calling context-sensitive methods (or subrefs), and its obnoxious scoping system.

While these limitations don't show up at first, especially when using code that's been written with TT in mind, they become more and more painful as time goes on.

There are a few reason to use template language that isn't the same as your programming language. The most important of these is simplicity for non-programmers and re-use across multiple languages. I don't find TT to be much simpler than baby talk Perl, although it is a bit simpler, when the stash is made to contain only things that can be used simply in TT. TT isn't well implemented in any other language, so that benefit isn't here.

I find HTML::Mason's template langauge and Text::Template to be much more useful for my needs.

Text-CSV_XS (0.37) *****

It reads all kinds of crazy insane CSV variants that crazy insane people throw at my software. Once or twice, when it wouldn't handle one, I complained to the author and he made it work very quickly. This is the place to start for CSV reading.

Return-Value (1.302) *

This is a dreadful idea. I can say that freely because it was mine. Not only does it return objects that magically dereference in all sorts of clever ways, but it may return objects that are *false*!

Throwing an exception on failure is a much easier to manage practice, and will surprise and confuse fewer programmers. Returning objects or throwing exceptions that have useful methods for inspection is better than using these generic "any kind of data attached" objects.

Please don't use this module for new code.

Nothing-Tiny (1) *

I assume this has been uploaded to troll Adam Kennedy after his low review of and ill humor about Moose-Tiny. This is a joke distribution, but it doesn't seem very funny. It's not even a clever bit of code. It's just a waste of space seemingly done for no good or entertaining reason.

Tie-CPHash (1.03) ****

It does what it says on the tin! Who could ask for more from this kind of module? I said to my self, I said, "I need a hash that will be case preserving and case insensitive," and then I searched the CPAN, and I found this. I replaced a few hashes with tied hashes, and my code worked as I wanted. That's all I ask from life.

Email-Folder (0.854) **

Email::Folder provides a very primitive interface to iterating over the contents of various kinds of email containers like Maildir and mbox, and extensions exist for POP and IMAP. The problem is that the interface is somewhat inefficient, very primitive and difficult to extend. Email::Folder can only read the contents of a folder. It can't alter messages, tell you where in the container the message was found, or delete messages -- and it doesn't interoperate efficiently with those modules that can.

I use this code for (and only for) saying "for each message in folder, do X," and eventually I'll probably get used to just using Mail::Box for that instead.

Tie-IxHash (1.21) ****

I only use it on rare occasions, but when I need it, it's great. It does exactly what it says: you get a hash that preserves order. Great!

Email-Handle (0.01) **

This module is one of the many email modules likely to cause you heartache when you need it for anything useful. It doesn't properly handle non-ascii characters (or other special characters) in the address, nor does it deal with email address phrases, comments, or groups. It assumes that you can parse an email address by splitting on @ and having two parts.

These are potentially fixable problems, but worse, it ties itself to MIME::Lite, one of the buggiest popular email modules on the CPAN. You are better off using Email:: or Mail:: Address.

HTML-Mail (0.10) **

This module is like MIME::Lite::HTML or Email::MIME::CreateHTML. Like the former, it uses MIME::Lite, and for that reason alone I suggest you avoid it. MIME::Lite is quite buggy, and best avoided in all situations. Investigate, instead, Email::MIME::CreateHTML.

Email-MIME-CreateHTML (1.026) ****

Finally! A replacement for the buggy, poorly constructed MIME::Lite::HTML. When your people now say, "We made a web page and we want to email it to people," you can very very easily do this without having to think about it. It takes care of all the annoying rewriting and attaching for you.

Net-Delicious (1.11) ****

This code made it really easy to write simple software to backup my bookmarks, convert them to other bookmark managers, and generally deal with my data. It deals with all the annoying XML stuff so you don't have to.

Net-Flickr-Backup (2.96) ****

It was a pain to install, and then I struggled with some issues about getting it running. Now that it's going, though, I can delete my iPhoto store and just back up Flickr. I won't lose comments, notes, descriptions, tags, or anything else that I didn't have in iPhoto. What a relief!

Test-Deep (0.096) ****

If you need to test a big data structure's content, and you don't know or care about every last little bit of it, Test::Deep makes it easy to specify exactly what you need to. You can say, for example, that some very deep node has a few given properties and that you don't care about anything else -- or you can build a complex structure of comparisons to be applied to your tested struct. It's a big time-saver.

Sub-Override (0.08) ****

This is one of those really excellent little tools that you hope you'll never have to use. The great thing about it is that it's so straightforward. It's very easy to use and does something that seems very complicated in a very simple way. I've only used it in production two or three times, but each time it has saved me from what would have otherwise been hours of refactoring (or hours of regretting horrible hack jobs).

Scalar-List-Utils (1.19) *****

The functions offered by Scalar-List-Utils are indispensable. It's hard to believe that some of them weren't in the core to begin with. Scalar::Util is one of the modules I used most often when writing routines that need to validate data or behave polymorphically. Learn and love these modules.

SQL-Abstract (1.22) ****

I've used quite a few bits of code that try to represent SQL queries as structures of constraints. They generally range from painfully horrible to painfully naive. SQL-Abstract is really quite good. It's got almost everything I've needed, and then enough flexibility at the edges that I've rarely had to entirely circumvent it to get the job done.

Pod-Coverage (0.18) ****

Darn useful! Even though Test::Pod::Coverage usually bites me just when I think I'm ready to release a module, I still love it. It saves me from sending a lot of undocumented code into the wild -- and this is the code that makes it go.

Perl-MinimumVersion (0.14) ****

I use this all the time to make sure I haven't stupidly added "warnings" to something that's supposed to work on 5.004. It's a simple-seeming task, but there are lots of annoying things to consider... and this code will consider them for you.

Perl-Critic (1.051) ****

What a great tool! Not only was I able to tweak its settings to get it to help me write code the way *I* wanted to write it, but then it was really easy to write my own plugins to test for things that configuration alone could get me.

Using Perl::Critic to enforce (or at least audit) your organization's coding guidelines is a great idea, and it's pretty darn good for personal use, too.

Params-Util (0.23) ****

I'll admit that I'm biased, as I contributed these parts, but... I really, really like having the _*LIKE routines around. It makes it much easier to let Perl be Perl and hand in variables that can act like what's needed without having to be exactly that. It lets my code be both flexible and validated.

PadWalker (1.5) ****

PadWalker is really, really useful if you need to debug something really, really weird. I hope you never have to use this module, but if you do, use it boldly: it's great. If only it could create new pad entries up the call stack...

PPI (1.118) *****

The first time I finally installed and tried using PPI, I was shocked. It was as easy to use as, say, the JavaScript DOM API, but instead of jumbling up HTML, I was scattering Perl constructs around the tree. It was fantastic, and I still find it incredibly useful, especially as the power behind Perl::Critic.

Module-Pluggable (3.6) ****

I have often seen Module::Pluggable abused to build overly-naive systems. Despite these atrocities, I will not blame Module::Pluggable. I've used it myself many times to build code that, surely, no one would call an atrocity. Right?

It's very useful, very easy to use, and it has just the right kind of configurability.

Module-CoreList (2.09) *****

It does one thing, and it does it very well. More important is the fact that this one thing is really really useful and would, without this module, be really really tedious. I use "corelist" very frequently and every time I feel like I just saved fifteen minutes of searching.

Mail-SpamAssassin (3.1.8) *****

For sheer usefulness, Mail-SpamAssassin can take on nearly any other distribution with one arm tied behind its back. Some of its default rules or scores bug me. Sometimes it causes me grief at work because I have to deal with quirks. Sometimes its configuration is hard to understand. None of this matters, because it saves me from seeing over 30,000 pieces of spam each month. Thanks, SpamAssassin!

Lingua-EN-Inflect (1.89) ****

I hate the interface -- but I'm not sure what would be better. It hardly matters: the module is so darn useful that you'll stop caring about the interface really quickly. I don't use it often, but when I do, it keeps me from looking like an idiots.

IO-String (1.08) ****

Normally, I prefer to just use the "ref for filename" version of open available in perl 5.8, but I'm often stuck working in perl 5.6, where this module can do just what you need. I've used it time and time again to replace passed-around filehandles with IO::String objects containing data retrieved in some other way.

Hook-LexWrap (0.20) ****

I have mixed feelings about Hook::LexWrap. I sort of wish it didn't exist, because it makes all manner of evil possible. Despite that, I've used it a few times (Sub::MicroSig, et al.), and it's saved me many hours of work. If you feel safe deciding that you want to add this kind of complexity to your code, it can be quite worth it.

HTTP-Server-Simple (0.27) ****

It's just so... useful! When I need to futz around with web application testing, I can just use this distribution to set up a dinky little server without worrying about Apache or any other server that requires more than a moment's thought. See also Test::HTTP::Server::Simple.

Filter-Simple (0.82) ****

Don't write source filters. They will make your momma cry. That said, if you really need to write a source filter because it will make your life a lot easier, or because you have a wicked idea for an Acme:: modules, and if your mother has already passed on to her great reward... then this module makes it really, really easy to write most filters. Use it, not Filter::Util::Call.

File-Find-Rule-Perl (0.03) ****

Sometimes the simple modules are the ones that you can really appreciate without complaint: there's so little to get wrong. Sure, this only saves me a few lines here and there, but they add up.

File-Find-Rule (0.30) ***

This is a huge, massive, major improvement over the interface of File::Find. I use it all the time. My only real qualm, and it's a big one, is that it doesn't provide an iterator. Instead, it does all the searching and returns a big result. For large searches, this can be a real drag.

File-HomeDir (0.64) *****

This has gone a very long way to making a lot of my code more portable. I've very often seen people (including Younger Me) use $HOME or getpwent blindly, leaving Windows or VMS users out in the cold. With this module, it's really easy to keep things Just Working.

File-Slurp (9999.12) **

I really liked this module until the first time I got bitten by its failure to interoperate properly with :encoding on filehandles. I've decided it's almost always easier to just localize $/ briefly and read that way. It's a little uglier and more piggish, but it's more likely to work in odd conditions.

EasyTool (1.0.4) **

I think that many, if not most, Perl programmers have modules like this: a bunch of random-ish routines that do Useful Stuff. I view these as a forgivable weakness more than a good design pattern, and it seems to me that propagating the pattern on the CPAN, in a top-level namespace is a bad idea. Potential users are better off finding the modules that implement, better, the handy tools they need.

The lack of an exporter and the mishmash of tools will make this module something of an albatross.

SVN-Notify (2.64) ****

This is a really useful tool that helps me keep track of what the rest of the team is doing. It does everything I need, and the author has been receptive to making it even easier to use.

Lisp-Fmt (0.01) *

I'd like to use this module, but it would be illegal. The license is completely vague and unenforceable, and because of this it is not safe to assume this code is legal to use.

This is a restrictive license. Some people, like say Richard Stallman, believe that it is unethical to use any restrictively-licensed software. That means that any choice to use this software may be considered unethical and is therefore not allowed under the terms of the license.

Why not just use a license that copyright lawyers have already looked at and deemed not unenforceable?

String-Work (1.00) *

The documentation does not explain all of the interface: for example, if you pass in arrayrefs, it acts on the first element in them.

The module says it requires 5.8.8, but seems do to nothing that didn't work in 5.0. It also dosn't do anything that isn't one line of code with core Perl.

File-ReadSimple (1.0) *

Do not use this. It is not for "no so good programmers" it is for writting "not so good programs." Its interface is not really any simpler than the core Perl interface for files. Worse, even though it requires 5.6, it uses antique global filehandles, to make it easier to introduce bugs.

cwd (HASH(0x8755d80)) **

Cwd already exists, so cwd is confusing, especially to (for example) the HFS+ filesystem. Why is this a pragma, anyway? Why aren't there any useful tests? Why is there no version number on the dist?

Writing an extra line of code would be better than using this.

Test-Pod-Coverage (1.08) *****

This is one of those modules that I always forget about until it saves my butt. I put a pod-coverage.t in all my distributions (actually, Module::Starter does that for me) and from then on, before I release a module, I'm reminded if I've written code that has no documentation.

I never have to think about it, it just tells me when I've made a mistake, and then I fix it. That's a nice kind of tool.

UNIVERSAL-clone (0.01) *

Good grief, make it stop!

UNIVERSAL is not a place to stick things that you think you'd like to use a lot. It really, really isn't. It would have been fine to write a mixin that provides cloning. Hey, you could even give an example showing that you could mix in to UNIVERSAL, if you're completely evil.

Uploading this distribution outside of Acme with a straight face is wrong wrong wrong. I hope the author sees the light and withdraws it.

Sub-Installer (0.0.2) **

This module is a great idea. When I first saw it, I sort of muttered about how it was just a tiny convenience. After I gave it a little thought, though, I realized that the kind of convenience this provided was just the kind of convenience that I wanted. It hid a lot of the ugliness that makes code harder to read and understand without thinking.

Once I finally started to use Sub::Installer though, I realized that it worked not by mixing into classes as requested, but by installing into UNIVERSAL, with no recourse to do otherwise.

I liked the idea enough to implement my own, similar solution, and it makes me very happy. The idea is great. The implementation just goes too far.

HTML-Tree (3.1901) *****

I used to do my HTML munging in HTML::TokeParser. The TokeParser is a useful module, but it's very different from the kind of tree-traversal that you get used to after writing JavaScript. If you are used to working with HTML via the JavaScript DOM, HTML::Tree will be much more like what you're used to. In fact, you'll start wishing that the DOM was more like HTML::Tree.

The documentation layout is unusual, but the documentation itself is quite good. If you need to muck about with HTML, this is the place to start.

Getopt-Long-Descriptive (0.02) ****

After using Getopt::Long::Descriptive, Getopt::Long is like using a very complicated set of s/// expressions to replace printf. GLD is the new hotness.

List-Cycle (0.04) ****

Nice, simple way to flip through a bunch of values without thinking about it. (I use it for the stereotypical example reason: alternating row colors in a table.) It's like Tie::Cycle, but more mutable. It's also nice to avoid tying.

List-MoreUtils (0.12) *****

If I were an array object, I would want these as my methods. They do all the things you hate writing over and over, and a bunch more things that you'll realize you should've been writing but never did. It makes List::Util look like a tinkertoy.

Test-WWW-Mechanize (1.06) *****

If you write web applications, you probably need this module. It's like the beautiful love-child of Test::More and WWW::Mechanize. You say, "Go here and do this, and that should happen" and it takes care of telling you how you screwed up. Sure, you could just use WWW::Mechanize and a bit of glue to make it work with Test::More, but why bother? This modules makes web testers happy.

WWW-Mechanize (1.14) *****

Oh, Mechanize, how do I love thee? Let me count the ways: *****

I used to think, "I guess Mechanize is OK if you're into that sort of thing." Then I realized that getting into that sort of thing would save me endless hours. A WWW::Mechanize script need not be much more than: "go to this page; click that link; fill out the form as follows; submit; print the result from that paragraph." It just does what you want, quickly and easily.

File-Temp (0.16) ****

I'll say up front that one of two of the interface decisions in File::Temp bug me. Some things are given confusingly-similar names, and then there's CLEANUP => 1. In the end, though, these minor quibbles are overshadowed by the incredible usefulness of self-destroying files and directories. My test scripts abound with File::Temp use; make a directory, go hog wild making files in it, and when you're done it goes away. Dump logs into tmpfiles for analysis. Later on they're gone. Totally freaking awesome.

Exception-Class (1.22) *****

It's Perlish! It's sophisticated exceptions! It's not a contradiction!

Like so much Rolskyware, Exception::Class provides a well-engineered and very customizable system for doing something that most large software needs: error trapping. It has an optimal interface (especially with the addition of Foo->caught), a simple and Perlish way to define exception hierarchies, and reasonable default behavior. Use it.

Getopt-Long (2.34) ****

Getting command line options and dealing with them is a colossal pain, and every module that does it sucks and offends someone. Getopt::Long doesn't always do what I want, and doesn't always act how I expect, but it's much closer than anything else. Given the number of different desires and expectations out there, and the fact that so many people aren't much more offended than I am by Getotp::Long, it must be doing something right!

Email-Simple-Creator (1.4) ****

If you are using Email::Simple and you want to make a new message from scratch, you need to use this class. Do I need to say anything else? This is essential.

Email-Simple (1.92) ****

It's email! It's simple! What more could you want? Well, sometimes it seems a bit too simple, since you need to use other modules to add MIME support or a constructor, but in the end that simplicity is surely what helped make it easy to write, test, and promulgate.

If you're handling mail, this is the way to go.

Inline-TT (0.06) ****

This is a great time-saver for simple scripts that need to produce useful, involved output but shouldn't have to have files lying about all over the place. I stick TT blocks in my DATA section all time time in scripts, now, and it's really pleasant.

Tie-Hash-RegexKeys (1.2) *

Do not use this module.

tie my %h, 'Tie::Hash::RegexKeys';

# hash things...

my @keys = tied(%h)->FETCH_KEYS(qr/$pat/);

Is this module's way of saying:

my %h;

# ...

my @keys = grep {/$pat/} keys %h;

...but it's slower and takes longer to type.

Exception-ThrowUnless (1.04) *

It's like Fatal, except you have to use different routine names and there's no documentation outside of the README. So... use Fatal.

Kwiki (0.38) ***

Kwiki is extremely easy to install and use without knowing much about Perl or Kwiki itself. Installing extra features through plugins is also usually fairly painless. The only concern most users should expect is speed: Kwiki tends to run on the slow side.

Kwiki, and the Spoon framework on which it was built, provide a very powerful and flexible way to write plugins to modify and extend the behavior and feature-set of Kwiki. Unfortunately, it is nearly entirely undocumented. While a few efforts to improve this are underway, none have yet to bear much fruit.

TimeConvert (TimeConvert0.5) *

A lousy reimplementation of Time::Duration, with nothing to do with unix epoch seconds. It converts durations in seconds to English, using an object for no clear reason.

Use Time::Duration

Bryar (2.6) ****

Bryar is a very nice start for a simple but extensible blog framework. It has some quirks and design issues, though, especially in the layout of the controlling Bryar class. Still, using Bryar made it very easy for me to re-implement my awful blog with all of its original features, plus more, in just an hour or two. Extending Bryar with new features and sources has remained very easy, and I look forward to seeing it develop in the future.

Text-Table (1.102) ****

This is another one of those modules that does one of those awful, stupid tasks that every programmer hates doing. It prints a nice text table, perfect for creating simple report output. There are piles of bells and whistles for customizing the display, but I rarely go much past the options in the synopsis. It's definitely saved me from spending hours writing awful display code (or shipping really ugly reports).

DBD-SQLite (1.06) *****

Excellent! I just "make install" and I have a complete database manager. I don't need to pollute my laptop or workstation with a server installation, I can pass the database files around from platform to platform, and I can distribute SQL-reliant tests without requiring a big scary RDBMS.

I see a lot of personal database applications coming on...

Win32-OLE (0.17) ****

This module has saved me days of writing VBA by making all of VBA's utility available in Perl. I have dozens of scripts, now, to automate the creation of complex reports in Excel. Our engineers have used Win32::OLE to interface with Windows-based statistical analysis software. Without VBA in the way, it's surprising how useful the object model of many Microsoft applications can become.

Win32::OLE can save you from writing Visual Basic, and that oughta be enough for anyone.

Mac-Glue (1.21) ****

It's modules like this that make me /really/ wish there was a Usefulness metric in ratings. The documentation isn't great on the "doing simple things" front, because most of that sort of thing can be gleaned from the AppleScript docs for the applications you'll want to use. The system isn't painless to use, because AppleScript and Apple Events are painful things. The interface is great, considering that it has to mimic a considerably less great interface. Despite all this, the point is that Mac::Glue is insanely useful. It frees me from most of the shackles of AppleScript, lets me tie my Mac's programs to the entire might of Perl, and almost always works as I've learned to expect. Any serious Perl-on-Mac user needs to understand this module.

cpan-upload (2.2) ****

While it's been replaced (for me) by Module::Release, cpan-upload was my prime method for releasing modules until very recently. It saved me from going through the (often slow) PAUSE web interface and from using FTP, which I can't stand. After one release, it will have paid for its setup time. After two or three, you won't upload modules without it.

release (0.23) *****

Uploading to the CPAN used to be really annoying: checking every detail, building a dist, ftp, claiming the file. Sure, they're all easy, but they're boring. Then came cpan-upload, which at least made it easy to get the file onto the CPAN.

release goes much further. It checks your CVS, it tags releases, it catches lots of the bonehead mistakes you (read: I) make. I'm going to use this on all my distributions from now on, and you should, too!

Devel-Cover (0.47) *****

Devel::Cover has changed the way I build software. It shows me how inadequate my tests are, and challenges me to do better next time. Paul has done an incredible job, and it just keeps getting better. This module is destined to be into one of the most useful (and hopefully popular!) development tools on the CPAN.

Mail-Sendmail (0.79) ****

It's all about the interface! While it isn't perfect, or even phenomenal, it is phenomenally easy. I can drop in quick email notices wherever I want, without hassle, and it just works on Win32, GNU/Linux, and Mac OS. Excellent.

Date-Object (0.02) *

The code underlying this module is a maze of twistly little mistakes, all different. The math is not all right. The documentation is adequate, but more a mechanical listing of things than a good set of docs. This is not a viable alternative to DateTime.

Perl-Tidy (20031021) *****

Having inherited a few large chunks of awful Perl, I first spent an hour or two running through the code and fixing indents, newlines, and other garbage like that. It sucked the will to live out of me! People kept talking about Perl Tidy, and I kept thinking, "Great, now I can make my code look like what somebody else wants." Once I finally bothered looking at it, though, I found that it could be configured to make the code look almost exactly as I would've written it!

It's extremely configurable, and the documentation is fantastic, including a Choose Your Own Adventure-style quickstart. Every maintenance programmer needs Perl Tidy.

Text-Replace (0.07) *

Another module from SOFTDIA that makes no sense. It doesn't seem to /do/ anything that Perl doesn't already do. It comes with piles of documentation that explain everything except for the module. It's packaging is just weird. Why does this module exist? The implication, by the documentation, that this code is being used by is... disappointing.

Net-Netid (0.02) **

I'm not sure what this module is trying to accomplish, over and above the well-known and well-used Net::DNS module. Its interface is bizarre: it can be called with arrow notation, but is not really object or class oriented in any way. Some subs/methods return hashrefs, some return lists. IP addresses are expected as packed integers.

I don't get it.

CGI-Application (3.22) *****

Whenever I started a new CGI throwaway at work, I began by taking one of my old scripts and stripping everything but the setup, teardown, and dispatch table. By the time I was frustrated enough to write it all into a module, though, I remembered the article on CGI::Application and gave it a go. Not only did it do everything I needed, but it did it better and with a few features I never realized I needed. With a little subclassing, my usual CGI skeleton went from half an hour to ten seconds. This module makes my life easier.

CGI-Minimal (1.11) *****

Thanks to CGI::Minimal, I have almost never needed to use CGI. Minimal provides all the functions I'm used to using in a smaller, easier to grok package. It Just Works.

Test-Simple (0.47) *****

This is almost certainly my most-used distribution. Everything I write that is more complex than a few-liner gets a test or two (or more), and almost all my tests start with Test::More. The interface is straightforward (although a few sub names are slightly confusing) and the tutorial is just right. Learning to use Test::More is a prerequisite for any serious Perl programmer.

Test-Harness (2.40) *****

The basic test harness is all well and good, but prove is where it's at. It makes running my tests, all together or one at a time, to gather information or just to ensure correct functionality, trivial. prove has made me want to write more tests, organize my tests more clearly, and has made testing easier to force on coworkers. It's like there's a party in my test directory, and everyone's invited.

Lingua-EN-Numbers (0.01) ***

It does what it says: you give it a number and it gives you that number represented in English. To be honest, it's missing features (non-US English, for one thing) and not super-elegant, but it Just Works, and I can drop it into my projects without having to think about it. Good enough for me!

DBD-ODBC (1.06) ****

DBD::ODBC makes my job possible. Dealing with MS SQL 2000 is painful through other means, for reasons too excruciating to describe here. It works just as it claims to, and its documentation is honest about where the DBD falls short or is prevented from proper action by ODBC. (Painful example: only one sth per dbh allowed.)

Still, this gets installed on any Win32 workstation I'm forced to use.

Date-Calc (5.3) ***

This module does most of what I need, and it isn't terrible at it. It's just strange. It has a somewhat clunky interface (Nth_Weekday_of_Month_Year is too long for a sub name) and often strikes me as providing strange ways of solving its problems. Hopefully DateTime will obsolete Date::Calc.

Net-IRC (0.74) **

This module has always made me sad. It performs such a useful function, but is so unintuitive and weird that I've never felt like it allowed me to make my code beautiful through its use. Look at POE's IRC instead.

DBI (1.37) *****

The DBI is the single package that has made my life easier than any other non-Core module. I learned it once and now use it every day on multiple RDBMS. It is Just Right.