|Just another Perl shrine|
Re^4: The Most Essential Perl Development Tools Todayby schwern (Scribe)
|on Jan 03, 2013 at 22:07 UTC||Need Help??|
Perl::Critic's power is not in slavish devotion to its default rules, its in its ability to be configured, its robotic ability to run the same checks again and again, its ability to communicate your style to the rest of your project, and its ability to teach new styles.
Configuration: Shutting up Perl::Critic with #nocritic is not how you do it. Like any other system that gives you false warnings, you will eventually get frustrated playing whack-a-mole and start ignoring them. There is a .perlcriticrc which has per project and per user configuration. You can turn rules on, turn rules off, change their severity and generally configure them. Here's the .perlcritic from Test-Simple. Perl::Critic has to pick something for its defaults, they're never going to be acceptable to everyone (though some of them are whoppers), accept that and put a little effort into configuring it.
Repeatability: This leads to the second strength of Perl::Critic, its your robot monkey. Like automated tests, the great strength of Perl::Critic is that it can perform the same mind numbingly complicated task over and over and over again and do it perfectly (or at least equally wrong) every time. While humans might be better than robots at making heuristic decisions, which really good style judgements require, humans are terrible at making repeated rote judgements. This is what Perl::Critic aims to do, the simple (and sometimes not so simple) judgements, across acres of code, again and again. This leaves the humans to do what they're best at. I've been programming Perl for 15 years and Perl::Critic still picks up mistakes. In fact it just found a case where I forgot to turn on strict and warnings, how about that.
Perl::Critic also acts as the pair over your shoulder saying "can't you do that better?" Is that variable declared with too broad a scope? Shouldn't you use three arg open? Do you really need to turn off strict refs for the whole subroutine? Couldn't you do that with a dynamic method call rather than an eval STRING? Did you forget an explicit return?
Communication: This leads into the next strength of Perl::Critic, if you put a .perlcriticrc in your project then everyone working on the project gets to use it. Along with a .perltidy, .perlcriticrc clearly communicates and checks the project style without having to read a big out of date wiki page or something. Whether your contributor is a novice who doesn't know what they're doing, or an expert that THINKS they know what they're doing, perlcritic and perltidy make it very easy for them to review their code and follow the standards.
As important, those standards are written down and must be followed by all. This avoids the common case where the project leader makes it up as they go along, and gets to commit sloppy code when they want to. The perlcritic policy chosen by the project might stink, but at least its a known quantity that everybody has to live with. Once its known, it can be debated and fixed in a useful manner. perlcritic and perltidy have kept me honest.
Education: Finally, perlcritic teaches you things. Maybe it just constantly complains about a bad or out of date habit you have, or maybe it shows you something totally new. Three arg open is a great example, perlcritic has knocked that habit out of me. For newbies, bareword filehandles would be a very common one (considering the Perl documentation is loaded with them).
And it doesn't even have to be a human its teaching, it might be a very old code base. The ancient ExtUtils::MakeMaker code is now much better because we put some work into making it pass basic perlcritic. Auditing all that code by eye would have taken stupid amounts of time and I'm sure we'd have been much lazier about it.
I don't agree with many things Perl::Critic does by default, but its defaults are Perl::Critic's great weakness. Play to your tool's strengths instead. If you're devoting your energy to fighting Perl::Critic's default rules rather than configuring them, perhaps you have an issue with authority.