note
chromatic
<p>A few small nits. Be careful with this:</p>
<code>foreach (@plugin_list) {
require $_ or warn "Plugin $_ failed to load";
}</code>
<p>As your next example demonstrates without explaning, <code>perl</code> evaluates [require] EXPR (where EXPR is <em>not</em> a bareword) to requiring a filename, not a module name.</p>
<p>Also this code can be wrong in certain cases:</p>
<code># Initialization:
foreach (@plugins) {
$_->init if UNIVERSAL::can($_, 'init');
}</code>
<p>Consider if I'd implemented my own <code>can()</code> method:</p>
<code>#!/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";
}</code>
<p>I realize that this is a silly example, but there are very valid reasons to override <code>can()</code>. I'd rather write your snippet as:</p>
<code># Initialization:
foreach (@plugins)
{
eval
{
return unless $_->can( 'init' );
return $_->init();
}
}</code>
<p>If you document that <code>init()</code> should always return true, you can put a guard after that [eval] to see which plugins initialized successfully.</p>
<p>Alternately, if you want to see that an object you've somehow created or received performs specific behaviors, you could use [CPAN://Class::Roles].</p>
366279
366279