我怎样才能 运行 在我的 Perl 脚本中使用相同的代码并尽可能减少代码重复?

How can I run the same code throughout my Perl scripts with as little code duplication as possible?

我有一个子例程 csay,它是在 Perl class(程序包)中定义的。它有几个子classes,运行 该子例程经常和自始至终。它的行为取决于几个变量(其中大部分必须作为参数给出),其中一个在任何词法范围内都是常量($debug_level)。我试图尽可能避免重复代码,包括必须每次都将“常量”变量作为参数传递或在每次使用前加上前缀 $self->.

我不反对使用编译时替换(如果 Perl 中存在这样的东西),但我想尽可能避免使用实例(blessing 哈希等)。请参阅下面的示例,了解我正在尝试做的事情。有什么想法吗?

package SystemManager::Action::Generic;

sub csay($self, $cur_debug_level, $min_debug_level, $message) {
    if ($cur_debug_level >= $min_debug_level) { print("$message\n"); }
}

sub prepare_system($self)...

package SystemManager::Action::Backup;
use parent "SystemManager::Action::Generic";

sub backup_system($self,$debug_level,@files) {
    $self->csay($debug_level, 1, "Starting backup");
    $self->prepare_system();
    $self->csay($debug_level, 1, "Iterating through files");
    for my $file in (@files) {
        $self->csay($debug_level, 2, "Processing $file");
        ...
    }
    ...
}

csay 不需要 成为同一个 class 的一部分;最重要的部分是不必每次都指定 $debug_level 作为参数。

据我所知(如果我误解了请澄清)您可以将 $debug_level 存储在父 class:

#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);

my $debug_level = shift @ARGV || 0;
my $manager = SystemManager::Action::Backup->new($debug_level);
$manager->backup_system();
exit 0;

package SystemManager::Action::Generic;
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);

sub new ($class, $debug_level) {
    my $pkg = ref($class) || $class ;
    my $self = bless {debug_level => $debug_level}, $pkg;
    return $self;
}
    
sub csay($self, $min_debug_level, $message) {
    if ($self->{debug_level} >= $min_debug_level) { print("$message\n"); }
}

package SystemManager::Action::Backup;
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);

use parent -norequire, "SystemManager::Action::Generic";

sub backup_system($self, @files) {
    $self->csay(1, "Starting backup");
    #$self->prepare_system();
    #$self->csay(1, "Iterating through files");
    #for my $file in (@files) {
    #    $self->csay(2, "Processing $file");
    #    ...
    #}
    #...
}

作为 的替代方法,您可以使用可导出的 our 变量:

package SystemManager::Action::Generic;
our $cur_debug_level = 0;
our @EXPORT = qw($cur_debug_level); # or @EXPORT_OK to export explicitly only

sub csay($self, $min_debug_level, $message) {
    if ($cur_debug_level >= $min_debug_level) { print("$message\n"); }
}
    
package SystemManager::Action::Backup;
use parent "SystemManager::Action::Generic";

sub backup_system($self,@files) {
    $self->csay(1, "Starting backup");
    $self->prepare_system();
    $self->csay(1, "Iterating through files");
    for my $file in (@files) {
        $self->csay(2, "Processing $file");
        ...
    }
    ...
}

package main;
use SystemManager::Action::Backup;
$cur_debug_level = 2;
my $backup = Backup->new();
$backup->backup_system(<*.txt>);