mar*_*ton 5 language-agnostic error-handling perl
我用一个小模块包装了Perl的Net :: SSH :: Expect,以减少编写用于HP iLO卡的新配置脚本所需的样板代码.虽然我一方面希望这个包装器尽可能精简,但非程序员同事可以使用它,我也希望它尽可能好地编写.
它的使用方式如下:
my $ilo = iLO->new(host => $host, password => $password);
$ilo->login;
$ilo->command("cd /system1");
$ilo->command("set oemhp_server_name=$system_name", 'status=0');
Run Code Online (Sandbox Code Playgroud)
这是iLO::command():
sub command {
my ($self, $cmd, $response) = @_;
$response = 'hpiLO-> ' unless defined($response);
# $self->{ssh} is a Net::SSH::Expect object
croak "Not logged in!\n" unless ($self->{ssh});
$self->{ssh}->send($cmd);
if ($self->{ssh}->waitfor($response, $self->{CMD_TIMEOUT}, '-re')) {
return {
before => $self->{ssh}->before(),
match => $self->{ssh}->match(),
after => $self->{ssh}->after(),
};
} else {
carp "ERROR: '$cmd' response did not match /$response/:\n\n",
$self->{ssh}->before()),
"\n";
return undef;
}
}
Run Code Online (Sandbox Code Playgroud)
我有两个相关的问题.首先,我应该如何处理与预期响应不匹配的响应?我想我现在正在做的事情是令人满意的 - 通过返回undef我发出信号,我croak()会输出一个错误(虽然不是很优雅).但感觉就像代码味道.如果Perl有异常,我会提出一个并让调用代码决定是否忽略它/退出/打印一个警告,但它没有(好吧,在5.8中).也许我应该返回一些其他iLO::response带有错误信息的对象(或其他东西)和$ilo->before()(只是Net :: SSH :: Expect's before())的内容?但是,如果我这样做 - 并且必须将每个人都包裹$ilo->command在测试中以便捕获它 - 我的脚本将再次充满样板.
其次,我应该回归什么才能获得成功?同样,我的哈希包含来自Net :: SSH :: Expect的响应或多或少可以完成工作,但它不会以某种方式感觉"正确".虽然这个例子在Perl我的代码在其他语言中发出了同样熟悉的气味:我从来不知道如何或从一个方法返回什么.你能告诉我什么?
如果你熟悉的,如Java语言异常,然后想die作为throw和eval作为try和catch.而不是返回undef,你可以做这样的事情:
if ($self->{ssh}->waitfor($response, $self->{CMD_TIMEOUT}, '-re')) {
return {
before => $self->{ssh}->before(),
match => $self->{ssh}->match(),
after => $self->{ssh}->after(),
};
}
die "ERROR: '$cmd' response did not match /$response/:\n\n"
. $self->{ssh}->before();
Run Code Online (Sandbox Code Playgroud)
然后,在您的调用代码中:
eval {
$ilo->command("set oemhp_server_name=$system_name", 'status=0');
};
if ( my $error = $@ ) {
# handle $error here
}
Run Code Online (Sandbox Code Playgroud)
就像其他语言中的异常一样,这允许您在任何时候摆脱子方法,而不必担心在调用堆栈中传播返回值.它们将被eval发现它们的第一个块捕获.此外,您可以die再次重新抛出一个无法处理备份的异常.
更好的是,您可以使用die抛出一个对象,您的异常处理程序可以查询该对象以获取有用的信息和错误消息.我喜欢为此目的使用Exception :: Class.该错误模块提供了这样做类似Java的try/catch块,还有一些语法糖.