"They use your modulino but subclass it to change the run() subroutine and to override the parts they want to change."
This implies that the modulino is object-oriented ("subclassing" and "overriding"). Now, I'm not sure that you intended this statement to be taken that literally since some of your modulino demonstrations featured functional interfaces. However, it brings up some interesting considerations...
In Mastering Perl, you introduced "Modules as Programs" using a purely funcational module. In
DDJ - Scripts as Modules, you introduced modulinos, recommending an OO style consisting entirely of class methods. This solely-class-method approach supports easy inheritance and overriding, but seems slightly less versatile when it comes to re-use of subroutines. For example, say Modulino::A has "run()" and helper function "buy()" so that buy() influences what run() does. Suppose that buy() is useful enough to be exported by Modulino::A for potential re-use. Suppose that Modulino::B wants to do exactly what Modulino::A does in its run method but to use a different buy()ing algorithm. If buy() is to be usable outside the modulino, it might be cleaner to design it as a plain function instead of a class method. Then buy() could be called as a regular function instead of PKG->buy()...
#######
package Modulino::A;
use strict;
use Exporter qw(import);
# buy() will be useful to others...
our @EXPORT_OK = qw( buy );
__PACKAGE__->run(@ARGV) unless caller;
sub run {
my ($class, $arg) = (@_);
$class->perform_modulino_specific_stuff;
buy($arg);
}
sub perform_modulino_specific_stuff {
my $class = shift;
print "[special stuff for Modulino::As]\n";
}
sub buy {
print "[very useful purchasing algorithm to buy ", $_[0], "]\n";
}
#######
package Modulino::B;
use base qw( Modulino::A );
use strict;
unless(caller) {
no strict 'refs';
# "override" Modulino::A::buy with Modulino::B::buy...
*{ "Modulino::A::buy" } = \&buy;
# re-use Modulino::A::run...
__PACKAGE__->run(@ARGV);
}
sub perform_modulino_specific_stuff {
my $class = shift;
print "[special stuff for Modulino::Bs]\n";
}
sub buy { print "[alternative way to buy ", $_[0], "]\n" }
#######
# Demonstrate use of Modulino::A's exported functions...
$ perl -MModulinoA=buy -le 'buy("camels and onions")'
#######
Now we can cleanly inherit and override as well as export. This mixed interface style seems to me to be the most versatile way to build modulinos. The only problem is that ugly symbol table modification, but it would probably happen rarely and could be automated and abstracted by another module (which is why I'm so interested in finding the optimal pattern...I'm considering developing a module to aid in the construction of modulinos). What do you think?