2010-05-03 6 views
6

Ich bin nicht begeistert von der argument-passing-Architektur, die ich für die (vielen) Perl-Skripten entwickle, die für einige Skripte entwickelt wurden, die verschiedene Hadoop MapReduce-Jobs aufrufen.Wie kann ich gemeinsame Argumente an Perl-Module übergeben?

Derzeit gibt es 8 Skripts (in der Form run_something.pl), die von cron ausgeführt werden. (Und mehr auf dem Weg ... wir erwarten irgendwo zwischen 1 und 3 mehr für jede Funktion, die wir zu hadoop hinzufügen.) Jedes von diesen hat ungefähr 6 identische Befehlszeilenparameter und einige Befehlszeilenparameter, die ähnlich sind, alle spezifiziert mit Euklid.

Die Implementierungen sind in einem Dutzend .pm-Modulen. Einige davon sind weit verbreitet, und von denen andere einzigartig sind ....

Derzeit bin ich vorbei die args global zu jedem Modul ...

Innen run_something.pl ich habe:

set_common_args   (%ARGV); 
set_something_args  (%ARGV); 

Und in Something.pm habe ich

sub set_something_args { (% MYARGS) = @ _; }

So dann kann ich

if ($MYARGS{'--needs_more_beer'}) { 
    $beer++; 
} 

Ich sehe, dass ich wahrscheinlich zusätzliche „gemeinsame“ Dateien haben, gehen die ich will werde args, passieren, so dass ich haben drei oder vier set_xxx_args Aufrufe an der Spitze jeder run_something.pl, und es scheint einfach nicht zu elegant.

Auf der anderen Seite schlägt es die Übergabe des ganzen dummen Argumentarrays in die Anrufkette, und die Auswahl und Weiterleitung einzelner Elemente in der Anrufkette ist (a) zu viel Arbeit (b) fehleranfällig (c) doesn ' t viel kaufen.

In viele Möglichkeiten, was ich tue ist nur objektorientiertes Design, ohne die objektorientierte Sprache trappings, und es sieht hässlicher ohne das Drum und Dran, aber dennoch ...

Jeder Gedanken oder Ideen?

Antwort

4

Werfen Sie einen Blick auf import in Getopt::Long. Sie übergeben Argumente an Ihr Modul durch use Module qw/.../ und greifen sie über das import Subroutine.

# Override import.                                             
sub import { 
    my $pkg = shift;   # package                                       
    my @syms =();    # symbols to import                                     
    my @config =();   # configuration                                      
    my $dest = \@syms;   # symbols first                                      
    for (@_) { 
     if ($_ eq ':config') { 
      $dest = \@config; # config next                                      
      next; 
     } 
     push(@$dest, $_);  # push                                        
    } 
    # Hide one level and call super.                                         
    local $Exporter::ExportLevel = 1; 
    push(@syms, qw(&GetOptions)) if @syms; # always export GetOptions                                
    $pkg->SUPER::import(@syms); 
    # And configure.                                             
    Configure(@config) if @config; 
} 
10

In der gleichen Richtung wie Pedro Antwort, aber ein Upgrade Moose und MooseX::Getopt zu verwenden, stellen ich die Gemeinschaft SO mit ... ein Elch modulino *: ein Elch-Modul, das aufgenommen werden kann und in der Regel als Modul ausgeführt oder separat als Befehlszeilenprogramm:

# this is all in one file, MyApp/Module/Foo.pm: 

package MyApp::Module::Foo; 
use Moose; 
use MooseX::Getopt; 

has [ qw(my config args here) ] => (
    is => 'ro', isa => 'Int', 
); 

sub run { ... } 

package main; 
use strict; 
use warnings; 
sub run 
{ 
    my $module = MyApp::Module::Foo->new_with_options(); 
    $module->run(); 
} 

run() unless caller(); 

Das Modul kann mit Hilfe aufgerufen werden:

perl MyApp/Module/Foo.pm --my 0 --config 1 --args 2 --here 3 

mit diesem Muster, Sie kann Befehlszeilenargumente mithilfe eines Moduls sammeln, das von allen anderen Modulen und Skripts mit denselben Optionen verwendet wird, und die Standard-Moose-Zugriffsmethoden zum Abrufen dieser Optionen verwenden.

* modulinos sind Module, die auch als eigenständige Skripte ausgeführt werden können - ein Perl-Designmuster von SO's brian d foy.

+2

Oder überspringen Sie einfach das Boilerplate-Hauptprogramm, konsumieren MooseX :: Runnable und sagen Sie 'mx-run MyApp :: Module :: Foo --args --go --here'. Keine Hacks erforderlich. – jrockway

Verwandte Themen