http://qs321.pair.com?node_id=366285


in reply to Draft - Writng plugable programs with perl.

A few small nits. Be careful with this:

foreach (@plugin_list) { require $_ or warn "Plugin $_ failed to load"; }

As your next example demonstrates without explaning, perl evaluates require EXPR (where EXPR is not a bareword) to requiring a filename, not a module name.

Also this code can be wrong in certain cases:

# Initialization: foreach (@plugins) { $_->init if UNIVERSAL::can($_, 'init'); }

Consider if I'd implemented my own can() method:

#!/usr/bin/perl -w use strict; package Foo; sub new { bless {}, shift; } my $bar = sub { return 'Bar!'; }; sub can { my ($self, $method) = @_; return $bar if $method eq 'bar'; return $self->SUPER::can( $method ); } package main; my $foo = Foo->new(); if (UNIVERSAL::can( $foo, 'bar' )) { print "UNIVERSAL thinks Foo can bar\n"; } if (my $bar = $foo->can( 'bar' )) { print "Foo can actually ", $foo->$bar(), "\n"; }

I realize that this is a silly example, but there are very valid reasons to override can(). I'd rather write your snippet as:

# Initialization: foreach (@plugins) { eval { return unless $_->can( 'init' ); return $_->init(); } }

If you document that init() should always return true, you can put a guard after that eval to see which plugins initialized successfully.

Alternately, if you want to see that an object you've somehow created or received performs specific behaviors, you could use Class::Roles.