Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jplindstrom (594)

jplindstrom
  (email not shown publicly)

Journal of jplindstrom (594)

Monday January 07, 2008
11:31 AM

Emacs: reformat parameter lists

So, this is a line-wrappingly long line.

my $link = API::Link->new({rel => 'meta:version', href => $uri->as_string, type => 'application/xml'}),

If you think that's not a long line, imagine a really long line with a lot of parameters for the sake of argument.

One param per line is much nicer in this case.

my $link = API::Link->new({
    rel => 'meta:version',
    href => $uri->as_string,
    type => 'application/xml',
}),

But it is a bit of a hassle to reformat by hand. Manual drudgery which easily makes me lose focus on why I just just wrote that method call. Now, why did I create that $link again?

Here is some nice elisp I wrote to reformat parameter lists either into a single line, into multiple lines, or toggle between the two.

So just put the cursor somewhere inside the parameter list and hit C-o m p (or whatever key binding strikes your fancy, but this one will work well with out-of-the-box PerlySense conventions) and it will reformat things into the other layout.

Once you have the nice multi-line layout, you can also align the parameters if that makes things look more sensible. Hit C-o m a et voila:

my $link = API::Link->new({
    rel  => 'meta:version',
    href => $uri->as_string,
    type => 'application/xml',
}),

Well, not that much difference with those parameter names, but I can't be arsed. You get the picture.

Enjoy!

(Now I'm just waiting for someone to tell me I reinvented the wheel. I just couldn't find any.)

Sunday January 06, 2008
03:59 PM

Cohesive source formatting

After reading my last journal entry, Ovid and I started talking about how to format source code. He prefers one blank line between the POD docs and its sub, and one blank line between the sub and the next sub (I think it was) over my keeping the sub and its POD together, and separating different subs with three blank lines.

Having this kind of discussion can easily become very unproductive and stupid if you just spew opinions. But it becomes interesting if you can avoid the "what" and instead drill down to the "why" of things. Being challenged about opinions is good because it makes you figure out the reasons behind them and hopefully it clarifies your thinking in some way. You may even change your mind (imagine that!).

I often find that whenever I need to explain why I do something it boils down to a principle or rule of thumb or other that I have picked up over the years. And if I can't find a rule of thumb, thinking about it may make me formulate one which is also a win.

The Principle of Proximity

In this case of where to put whitespace (or not), it is the Principle of Proximity. Since this issue is all about reading source code, it comes from the area of typography and visual design.

The Principle of Proximity tells you to put related items close together physically. Things that aren't related should be farther apart. The amount of separation between items or groups tells your reader how the material is organized.

In short: Things that belong together should be together.

So this is why I don't like source to look like this:

}

=head2 run_safe($c, $sub, $fail_action, $fail_message, @rest)
...
=cut

sub run_safe {
    ....
}

=head2 class_to_moniker($class_name)
...
=cut

sub class_to_moniker {
    ...
}

To me, even with proper syntax highlighting that just blurs together into a grey goo. It's obvious from convention that the POD comes before the sub, but otherwise there isn't enough visible structure to it.

The Principle of Proximity is very similar to the concept of Perceived Affordance from Don Norman's The Design of Everyday Things. Translated to web design, this basically becomes: If it is a button, it should look like a button. and if it looks like a button it should be a button. Anything else will guide the user in the wrong direction.

Translated to source code: if things belong together, it should look like they belong together. If things look like they belong together, they should belong together.

In source code, the belonging is indicated by visual grouping, which is why I much prefer grouping the sub and its POD block into a visual unit, and separating the individual subs with vertical whitespace, like this:

}



=head2 run_safe($c, $sub, $fail_action, $fail_message, @rest)
...
=cut
sub run_safe {
   ....
}



=head2 class_to_moniker($class_name)
...
=cut
sub class_to_moniker {
   ...
}



See? Two things. At a glance.

One argument for not putting too much vertical whitespace between subs is that it limits the amount of code visible on the screen. But while I sympathise with that idea, because each individual sub is the unit of interest at a given time, they are generally to be understood in isolation from each other. Separating them visually only reinforces this notion.

Friday January 04, 2008
01:18 PM

Source makeover

Badly formatted source code is ugly. But, a few keyboard macros later and it's much nicer.

And this little defun helped a lot, maybe someone will find it as useful as I did.

(defun jpl-makeover-remove-pod-sub-whitespace ()
  "Clean up Perl source whitespace formatting"
  (interactive)
 
  (save-excursion
    ;; Remove =cut with more POD as the next thing
    (replace-regexp "=cut\n\n+=" "\n\n=" nil (point-min) (point-max))
 
    ;; Remove whitespace between POD and sub
    (replace-regexp "=cut\n+sub " "=cut\nsub " nil (point-min) (point-max))
 
    ;; 3 newlines before subs if no POD
    (replace-regexp "\n\n+sub " "\n\n\n\nsub " nil (point-min) (point-max))
 
    ;; 3 newlines before =head...
    (replace-regexp "\n\n+=head" "\n\n\n\n=head" nil (point-min) (point-max))
 
    ;; ...except at the top POD block where it's more compact
    (replace-regexp "\n\n+=head1 NAME" "\n=head1 NAME" nil (point-min) (point-max))
    (replace-regexp "\n\n+=head1 DESCRIPTION" "\n\n=head1 DESCRIPTION" nil (point-min) (point-max))
    (replace-regexp "\n\n+=head1 SYNOPSIS" "\n\n=head1 SYNOPSIS" nil (point-min) (point-max))
    )
 
  (font-lock-fontify-buffer)   ;; In case it got confused
  )

Thursday December 27, 2007
05:13 PM

Springtime for Perl and Emacs

There seems to be a lot going on with Perl and Emacs at the moment.

Looking through the Recent CPAN Changes RSS feed I just found PDE, Perl Development Environment in Emacs.

Looks interesting, especially since I try to pick up as many clever elisp tricks as possible.

Sunday December 16, 2007
12:41 AM

Devel::PerlySense 0.0134

I just uploaded Devel::PerlySense 0.0134 to PAUSE. If you happen to use PerlySense [1], you may want to upgrade since a few nifty features have been added in the last versions:

  • Class Overview with the list of methods/properties that make up the API of the class (so that includes inherited methods). From this list you can use method Docs (d) and Go to (g), just like from within the source. [2]
  • In the Class Overview, things are rearranged a bit to show the most useful things at the top: the Inheritance tree and the API.
  • Run "perly_sense info" to display diagnostics about what PerlySense thinks your Project dir is, where your Home dir is located, etc.
  • A Cookbook page with clever tricks and common problem. Well, one of each so far.

I got a spontaneous That's fucking cool! reaction from a team mate the other day so if you happen to not yet use PerlySense, but use Emacs, you may want to give it a spin. I fixed the gripe in the CPAN review about fiddling with the elisp files, so that's one less hoop to jump through.

[1] I have no idea whatsoever if anyone actually uses this thing yet, but I'm guessing the user base is only slightly larger than... well, me.

[2] The API view is not at all finished yet, but it's still useful. Ideally, the methods should be ordered first by their POD heading, and then by their source location. And private methods of parent classes from outside the Project (i.e. when your classes inherit from CPAN modules) are rarely interesting and shouldn't be displayed at all, or at least be displayed in a more subdued font face.

Tuesday November 27, 2007
05:31 PM

Ruby -- first impressions

I did some Ruby work at work today. Initial impressions:

  • It's very Perlish. Mostly in a good way. No value sigils, but overall tighter syntax. No ugly dereferencing brace fest, and methods on basic datatypes makes for clean code if you are willing to make an effort.

    I remember someone saying Ruby is Perl's younger, hotter sister. Well, they are clearly related. And she is hot.

  • The block syntax is really nice.
  • Very sparse documentation of method definitions in this app. Not sure whether that's a project thing or a general Ruby/library thing. I mean, It's not like I have been spoiled rotten with well documented Perl enterprise source code historically.

    But wearing the maintenance hat, exploring a code base with zero prior knowledge clearly reveals the need to document what kind of objects are being passed around in a dynamic language. I wonder if the type inferring statically typed languages (Haskell) have the same kind of issues compared to explicitly typed languages (Java).

  • In Ruby, local variables are created on first use. No declaration of these seems... well, insane. This already bit me, and I've been using Ruby for, what, a day?

    I'm a bit curious about the phenomenon. In Perl there's "use strict" and then lexicals are declared with "my". That's such an obvious life saver and such a strongly encouraged practice that it's mind boggling to see people not using it. Not being able to use it. But at the same time... is this the way people using statically typed languages all day look at dynamic languages, not believing it's possible to live without type declarations all over the place?

    There are obvious benefits for understanding the code (see above) to have e.g. type information available in method signatures (not the least the ability to do static analysis of the code for refactorings and command completion, etc), just as there are obvious benefits to not having to care about it until the latest possible moment (late binding). So there's a trade-off there. And you can keep it somewhat sane by documenting as needed (folks, more true laziness, please).

    I can't see the potential advantage of not declaring lexicals. Maybe I'm missing something. Maybe I'll come around. But I'm guessing not, this seems like a genuine misfeature.

  • There seems to be two kinds of exceptions, those you "raise" and those you "throw". There is a distinction, I haven't quite figured out what it is yet though :) Right now I just find it interesting. Off to the manuals.
  • Lanuage documentation is decent. Usually a quick Google for anything yields useful results. Same seems to hold for ActiveRecord and friends, but I haven't been doing anything interesting with it yet.

All in all, a pleasant experience.

Monday November 26, 2007
04:14 PM

Crappy code

Google Video of Alberto Savoia on Crappy Code.

The basic premise of the CRAP metric is:
Complexity bad
Tests good

Test coverage is measured eminently with Devel::Cover. But how do we measure complexity of Perl code?

Perl::Critic implements the McCabe cyclomatic complexity thingy.

Does anyone have any actual experience whether that makes sense and is a useful metric? In general? For Perl?

Or what else can we use to indicate the crappiness of Perl code?

Saturday November 24, 2007
07:55 AM

At BarCamp

So Jonathan blagged me into BarCamp London.

Very interesting so far. Two economy related talks this morning:

  • VRM - Vendor Rights Management

    Turning the Vendor - Consumer relationship upside down and taking back the ownerhip of your transactional information

  • Voluntary Economics

I'm talking tomorrow about PerlySense and stuff.

Wednesday November 14, 2007
01:08 PM

Word of the Day: Budgetechture

I think the high cost of commercial databases (read: Oracle) leads to a kind of budgetechture that concentrates all data in a single massive database.

Looks like a very interesting blog in general. Check it out.

Wednesday September 12, 2007
11:47 AM

Don't dump everything in the entire world please

When dumping deeply nested data structures (like DBIC objects) and the indentation level wraps around the width of the shell yet another time, it's time to start doing this first:

local $Data::Dumper::Maxdepth = 3;

In the debugger, using "x" to dump, it's:

x [maxdepth] expr

This can also be set with the dumpDepth option so you don't have to care about it all the time:

o dumpDepth=3

In the debugger, using the excellent "r" to continue until return of sub, it also insists on dumping the return value (which you rarely care about, you just want to get out of the damn sub), unset the PrintRet option first.

o PrintRet=0

Put these in the .perldb init file in ./ or ~/ to make it permanent.

DB::parse_options("dumpDepth=3");
DB::parse_options("PrintRet=0");

No more eternal scrolling sessions.

* relief *