[San-Diego-pm] Meeting Minutes (2006-06-12)

Tkil tkil at scrye.com
Tue Jun 13 01:51:58 PDT 2006


I don't have the time to go into detail on these topics... (hears a
sigh of relief from the audience), but here's a quick summary of the
bits I heard at the meeting this evening.

0. Attendees:

Joel
Bob
Tkil
Nolly
Emile
David (?)

1. Module Naming.

Joel got caught out when his host added a "Utils.pm" to their perl
search path somewhere, and it started superceding his own package of
the same name.

Fix is for him to use this incantation if the .pm files are installed
into the same directory as his executables:

   use FindBin qw();
   use lib $FindBin::Bin;

This puts the directory containing the executable at the front of the
list of directories searched for modules.

2. Module / Package Naming.

How can one avoid this sort of collision?  It's a bit icky, but Java
solved this neatly: always use the reversed DNS name of a domain you
own (and is thus guaranteed unique).  So I'd put my code into 

   package Com::Foiani::Utils

or similar.  Overkill, and has the nasty side-effect of requiring lots
of extra directories, but it guarantees I'll never be caught out by
some new module showing up in the core distribution.

3. Shared Perl Code: .pm or .pl or ???

Joel then asked: why .pm at all?  Bob and I answered:

   a. BECAUSE WE SAID SO DAMMIT!

   b. Because it's the Perl 5 Way.  Ohm.

   c. Because "use" assumes it.

.pl is more of a perl 4 way; some people still use it for perl
executable scripts in the perl5 world, but I personally prefer ".plx"
for that.  *shrug*

4. Exporter.

Once you realize that using ".pm" with matching "package ..." decl is
the One True Way, the next step is to properly define the interface
into your module.  Until you understand why it's not always the
answer, using "Exporter" is always the answer.

Old Sk00l:

   use Exporter;
   our @ISA = qw( Exporter );
   our @EXPORT_OK = qw( function1 procedure2
                        $scalar1 @array2 %hashbob );

New Mod World:

   use base Exporter;
   our @EXPORT_OK = qw( ... )

This is all explained in perldoc perlmod, and be informed that using
@EXPORT_OK (instead of just knee-jerk defaulting to @EXPORT) is
possibly contentious.  But I'm Right.

5. Importing names.

Possibly a matter of taste, but I tend to import every single name
explicitly.  In Perl, I write bits like this:

   use File::Find qw();
   use File::Baseame qw( basename );

Instead of just the plain "use", which would bring in everything in
that module's @EXPORT list.

Likewise, I do the same in java:

   import java.util.ArrayList;
   import java.util.List;

Instead of "import java.util.*".

My rationale: having every import explicitly called out makes it
immediately obvious where to look for the function definition.  One
can perhaps argue that the IDE ought to keep track of it for you, but
IDEs can't help when you're reading code over the web or on a
printout.  Explicit imports work in both of those cases, and work
against some forms of typos (granted, rare cases).

6. File::Finder

I mentioned that I'd seen Randal pimping his File::Finder module on an
internal mailing list a few days back:

   http://search.cpan.org/~merlyn/File-Finder-0.53/lib/File/Finder.pm

It is intended to allow most (if not all) of the 'find' predicates to
be evaluated within perl itself.  This cuts back on crazy pipeline
abuse (and the contortions required to keep the quoting proper and
safe), as well as offering possible efficiency gains (one process
instead of 2+), and definite portability gains (e.g., no 'find' on
vanilla windows installs).

File::Finder also offers an interesting variant on the [where
possible] type-safe attribute construction pattern.  When creating a
new object, instead of using a constructor with zillions of
parameters, a "blank slate" object is returned instead.  Then a series
of attribute setters are called, each returning the object itself,
which allows for cascading calls.  For File::Finder, that looks like
this:

   my $big_or_old_files =
        $files->left->size("+50")->or->atime("+30")->right;

This actually leads to very readable code, but I initially found the
pattern a bit weird.  These days, I rather like it.

Nolly asked for a neutral analysis of the constructor/attribute
pattern vs. a parameter hash, and my list of advantages of the
constructor/attribute technique were:

   a. In strongly-typed languages, the attributes can be strongly
      typed.  Think:  new Car().color(RED).style(HATCHBACK)....

   b. Handling a parameter hash leads to big switch statements; the
      attribute method leads to small functions that do one thing.

   c. On the other paw, attriute methods tend to exclude immutable
      objects, which can suck for concurrent programming.

   d. On the third paw, one could have a ".finalize()" method that
      takes the object as currently attributed and make it immutable
      (that is, it returns an immutable instance).  Ding.

   e. Both offer the ability to inherit handling of attributes, but
      the attribute methods seem more natural.

   f. Spell checking of attributes is done by the runtime in the
      attribute technique, while you have to do it manually in the
      parameter hash method.

So not overwhelming, but I'd say that the constructor/attribute
technique is a handy tool in the arsenal.

7. Odds and Sods.

Fearful Lizard (that'd be me) is likely to be moving from San Diego to
Albuquerque, NM, in the next few weeks, so this might have been his
last meeting for a while.

David is going to YAPC and will try to blog/report thereon.

Joel is going to Ecuador and will seek perl geeks there.

Happy hacking,
t.


More information about the San-Diego-pm mailing list