The Value of Clean Code
In an O'Reilly LAMP blog post, "Clean Code is Easier to Debug", chromatic writes:
Consistent code requires much less brainpower to decipher its structure, leaving that much more brainpower to find real problems.
I have found this to be quite true and encourage any developer to give it a try. Since I've been paying more attention to how clean my code is I've found that not only can track down issues faster, but that I can refresh my memory of how a piece of code works faster.
"I don't have time for that though Tim," you might say. It doesn't take as much time and effort as you'd think.
The tool that I found most useful and to have the biggest impact on helping keep my code clean and consistent is perltidy. I use it on every piece of Perl code I touch -- and often. I've even gone so far as to use it on other's code when I'm having a hard time reading through it. For instance, there was a time when I'd run all of MT through, its improved a fair bit lately, it so I could figure out how to make us of it. (Documentation should do that, but we're not going there in this post.)
Try it. Here is the perltidy configuration file that I use.
-ce # cuddle-else
-lp # line up with parentheses
-syn # check syntax
-sfs # space for semicolon
-bar # open brace always on right
-nbbb # no blanks before blocks
-pt=2 # Parens tightness (tightest)
-bt=2 # braces tightness (tightest)
-sbt=2 # square brackets tightness (tighest)
You can customize how perltidy formats your code ad naseum. These are just my preferences.
Funny thing I noticed after using perltidy for a bit is that I started to write my code differently so it looked even cleaner once perltidy finished its work.
So while perltidy will make your code consistent and in a sense clean, that's not all there is to it. Clean code also means making code legible and well organized.
For instance, once put through the eye of perltidy I stopped writing long lines of code -- especially nested statements. So, I'd take a line like this:
my $count_iter = $class->count_group_by({
'asset' eq lc $type ? () :
(status => MT::Entry::RELEASE()),
%$terms,
},{
group => ['objecttag_tag_id'],
'join' => MT::ObjectTag->join_on('object_id', { object_datasource => $class->datasource, %$terms }, $args),
'asset' eq lc $type ? (no_class => 1) : (),
%$args
});
Note this is one lloooong line of code that takes time to dissect in order to understand everything it's doing. I found that my code was quicker and easier to read, understand and debug if I rewrote the same logic using smaller statements.
my $t = %$terms;
my $a = %args;
if ('asset' eq lc $type) {
$t->{status} = MT::Entry::RELEASE();
$a->{no_class} = 1;
}
$a->{group} = ['objecttag_tag_id'];
my $jt = {object_datasource => $class->datasource, %$terms};
my $join = MT::ObjectTag->join_on('object_id', $jt, $args);
my $count_iter = $class->count_group_by($t, $a);
Another benefit of this approach is that error messages are more accurate in pinpointing where the issue lies. In the first example, any error would be reported as the same line.
Another thing I started doing more was grouping variable assignments and declarations as much as possible. I found that practice made it quicker to find where and what you are assigning to a variable in a large block and its just neater with all those equal signs. (Yes like I once heard David Heinemeier Hansson say, "Call me shallow. I love beautiful code.")
There are a lot of little things you can do to make your code cleaner and more consistent. These are just two ways of many mostly smaller ones I've built in to my style.
If you are interested in learning more ways to write cleaner code I suggest checking out Damian Conway's Perl Best Practices. I don't agree with every practice that he evangelizes and some seem a bit over the top, but overall it's pretty good food for thought.
Incidentally many of the coding best practices from the book have been codified in Perl::Critic, a module that critiques perl source code issues warnings and errors based on the configured options. It has an extensible framework that has been used by many other CPAN developers to create many more policies. There are even modules for testing for Perl::Critic and testing perltidy compliance while running your testing suite.
Though I have every intention, I've yet to give Perl::Critic a try on my code nor have I worked both in to my standard test suite.
There is always room for improvement.

2 Comments