Mark Jason Dominus is a Perl hacker and book author with a blog. In one of his latest entries,
Clubbing someone to death with a loaded Uzi, he rather harshly critiques other people's (beginners) code. But whenever you do that, you should make sure your replacement code isn't dodgy itself.
There is no way to let people comment on the blog, so I'm posting my remarks here.
He writes:
It could have been written like this:Eww. There's a few red flags in there:printf FILE "$LOCATION{$location}\,"; printf FILE "%4s", "$min3\,"; printf FILE "%4s", "$max3\,"; printf FILE "%1s", "$wx3\n";
printf
where your data is used as a template. Granted, in this example, the data comes from a hash that is initialized with literal data stored in the script, but projects tend to evolve, and data just is not a template. If ever the data would contain a "%" sign, this code will blow up.
printf
? Put the comma in the template.
printf FILE "%s,%3s,%3s,%1s\n", $LOCATION{$location}, $min3, $max, $wx3;which is quite a bit shorter, and cleaner too, IMO.
foreach $location_name (%LOCATION ) { $location_code = $LOCATION{$location_name}; ...H*ll, if you want to loop over the keys of a hash, at least don't loop over both the keys and the values! Granted, in MJD's replacement code, the loop is gone, so this problem has disappeared too, but this is an major mistake that shouldn't just be skipped over.
foreach $location_name (keys %LOCATION ) { ...Otherwise, if ever one of your hash values is also used as a key in this hash, you'll get noise output.
printf FILE "%s,%3s,%3s,%1s\n", $LOCATION{$location}, $min3, $max, $wx3 if exists $LOCATION{$location};
MJD is certainly adept at spotting red flags.
Anything that I overlooked?
Yes: the point of his post.
It might have been useful if he had added a note to the effect that “this is still not very good, but it’s the first step to cleaning it up” – but a complete cleanup wasn’t what he set out to write about.
Re:The point.
bart on 2008-01-11T10:57:00
Well, I beg to differ. In my draft for this post I had originally written (and next dropped it as overly harsh):Leaving in the statementWhen you touch up code, any junk that you leave behind in statements that you touch, becomes your junk.now becomes his code.printf FILE "$LOCATION{$location}\,";
H*ll, if you want to loop over the keys of a hash, at least don't loop over both the keys and the values! Granted, in MJD's replacement code, the loop is gone, so this problem has disappeared too, but this is an major mistake that shouldn't just be skipped over.foreach $location_name (%LOCATION ) {
$location_code = $LOCATION{$location_name};
...
Re:I thought...
jjore on 2008-01-13T01:40:22
I thought it was interesting that MJD refactored the loop incorrectly. The original loop had the logic that if the key didn't exist in the hash, nothing would happen. MJD's refactoring caused it to be unconditional. That might be intended but it wasn't mentioned.
the following bit would have been more accurate.if ( exists $hash{foo} ) {
++ $hash{foo}
}