package Example::Foobar; =head1 NAME Example::Foobar - an example of module loader =head1 DESCRIPTION This module provides an example implementation of arbitrary module loader. Suppose you need to implement a command line utility that takes as its arguments a subcommand name (think of git) and its arguments. The subcommand should be implemented as an arbitrary Perl module that is saved somewhere in the Perl path. When the utility is called as, e.g. foobar A one two three the modue Example::Foobar::A will be loaded. It must implement two methods: B and B. The constructor B is called with the classname and command line arguments as its parameters. It is supposed to return an object of the class A prepared to do its job. Once the object is returned, its B method will be called to do the right thing. The actual implementation of the B command is as simple as use Example::Foobar; Example::Foobar->new(@ARGV)->run; See the B directory for examples of working command modules. Notice, that in real life each module would perhaps inherit from some common parent module. Here, for the purpose of clarity, each module is self-contained. =cut use strict; use warnings; use Carp; our $VERSION = '1.00'; =head1 CONSTRUCTOR =head2 new($class, ...) A command object fabric. Looks for a perl module for B<$class>, loads it and returns an instance of that class. Surplus arguments (B<...>) are passed as parameters to the underlying class constructor. =cut sub new { my ($class, $command, @args) = @_; croak "command not supplied" unless $command; my $modname = __PACKAGE__ . '::' . $command; my $modpath = $modname; $modpath =~ s{::}{/}g; $modpath .= '.pm'; my $cmd; eval { require $modpath; $cmd = $modname->new(@args); }; if ($@) { if ($@ =~ /Can't locate $modpath/) { die "unknown command: $command\n" } croak $@; } return $cmd; } 1;