Rob*_*nes 10 perl coding-style
在" Perl最佳实践 "中,AUTOLOAD部分的第一行是:
不要使用AUTOLOAD
然而,他描述的所有案例都涉及OO或模块.
我有一个独立的脚本,其中一些命令行开关控制定义特定函数的哪个版本.现在我知道我可以采取条件和描述并将其裸体放在我的文件顶部之前,但我觉得将它们放在文件末尾的AUTOLOAD中更方便,更清晰.
这是不好的做法/风格吗?如果你这么认为,为什么还有另一种方法呢?
按照布莱恩的要求
我基本上是用它来根据命令行开关进行条件编译.
我不介意一些建设性的批评.
sub AUTOLOAD {
our $AUTOLOAD;
(my $method = $AUTOLOAD) =~ s/.*:://s; # remove package name
if ($method eq 'tcpdump' && $tcpdump) {
eval q(
sub tcpdump {
my $msg = shift;
warn gf_time()." Thread ".threads->tid().": $msg\n";
}
);
} elsif ($method eq 'loginfo' && $debug) {
eval q(
sub loginfo {
my $msg = shift;
$msg =~ s/$CRLF/\n/g;
print gf_time()." Thread ".threads->tid().": $msg\n";
}
);
} elsif ($method eq 'build_get') {
if ($pipelining) {
eval q(
sub build_get {
my $url = shift;
my $base = shift;
$url = "http://".$url unless $url =~ /^http/;
return "GET $url HTTP/1.1${CRLF}Host: $base$CRLF$CRLF";
}
);
} else {
eval q(
sub build_get {
my $url = shift;
my $base = shift;
$url = "http://".$url unless $url =~ /^http/;
return "GET $url HTTP/1.1${CRLF}Host: $base${CRLF}Connection: close$CRLF$CRLF";
}
);
}
} elsif ($method eq 'grow') {
eval q{ require Convert::Scalar qw(grow); };
if ($@) {
eval q( sub grow {} );
}
goto &$method;
} else {
eval "sub $method {}";
return;
}
die $@ if $@;
goto &$method;
}
Run Code Online (Sandbox Code Playgroud)
另一种策略是将脚本编写为App ::*模块,并使用命令行选项选择要加载的类,以提供可插拔的功能,具体取决于选项.require一旦你知道它是什么,你就会准时到达那个班级.这是一个更前期的工作,但如果你打算长时间维护脚本,我敢打赌它会得到回报.在过去的几年中,创建了一些非常好的工具,用于创建功能真正存在于模块中的脚本,包括App :: Cmd,MooseX :: Getopt以及两者的混蛋后代.
我认为对于一个独立的脚本,这种方法是可以的.您可以动态创建子例程以加速后续调用,例如:
sub AUTOLOAD {
(my $name = our $AUTOLOAD) =~ s/.*:://;
no strict 'refs'; # allow symbolic references
*$AUTOLOAD = sub { print "$name subroutine called\n" };
goto &$AUTOLOAD; # jump to the new sub
}
Run Code Online (Sandbox Code Playgroud)
生成继承树时自动加载很棘手.
如果使用的唯一原因AUTOLOAD是将块重新定位到末尾,为什么不将其放在子例程的末尾,然后在定义其因变量后立即调用它?
sub tcpdump; # declare your subs if you want to call without parens
# define the parameters
compile();
# code that uses new subs
sub compile {
*tcpdump = $tcpdump ? sub {
my $msg = shift;
warn gf_time()." Thread ".threads->tid().": $msg\n";
} : sub {};
# ...
}
# EOF
Run Code Online (Sandbox Code Playgroud)
更好的是,如果其他地方不需要全局变量,只需将值作为compile参数传递即可。