这段代码闻起来......我该如何更好地重写它?
my $record;
eval {
while (
# undef $record here, so if getRecord() failed, nothing will be written
# in the reject file
do { undef $record; defined( $record = $dataFile->getRecord ) }
) {
$LT_DataFile->encode($record);
}
1;
};
if ( my $error = $@ ) {
$rejectFile->writeRecord( $error, $record );
}
感谢。
答案 0 :(得分:8)
您在catch部分中不需要变量,因为当执行到达时,其内容将始终为undef
。用文字值替换它可以让我们将$record
限制在更小的范围内。
use Try::Tiny;
try {
while (defined(my $record = $dataFile->getRecord)) {
$LT_DataFile->encode($record);
}
} catch {
$rejectFile->writeRecord($_, undef); # T::T puts error in $_
}
答案 1 :(得分:2)
好的,重写了我的答案。
我认为这里的 REAL 问题是你如何处理错误。当你有多个地方可能出错时,乍看之下看到一个错误处理程序是令人困惑的。我看到两种选择。
首先,保持它与现在大致相同,但具体检查每种类型的错误:
my $record;
eval {
while (defined( $record = $dataFile->getRecord )) {
$LT_DataFile->encode($record);
}
};
if (my $error = $@) {
given ($error) {
when (/get record error/) { $rejectFile->writeRecord($_, undef); }
when (/encode error/) { $rejectFile->writeRecord($_, $record); }
}
}
这样,您就明确了如何处理错误。当然,使用Try :: Tiny,这简化为以下
my $record;
try {
while (defined( $record = $dataFile->getRecord )) {
$LT_DataFile->encode($record);
}
} catch {
when (/get record error/) { $rejectFile->writeRecord($_, undef); }
when (/encode error/) { $rejectFile->writeRecord($_, $record); }
}
或者,您可以按Daxim's answer添加词法记录。这需要第二次评估或尝试,更接近问题并添加last
电话:
eval {
while (defined( my $record = $dataFile->getRecord )) {
eval { $LT_DataFile->encode($record) };
if (my $error = $@) { $rejectFile->writeRecord($error, $record); last }
}
};
if (my $error = $@) {
$rejectFile->writeRecord($error, undef);
}
不幸的是,这种方法不适用于Try :: Tiny,因为传递给try的块实际上是subrefs。
答案 2 :(得分:2)
我会将while
循环重构为
while (defined( $record = $dataFile->getRecord )) {
$LT_DataFile->encode($record);
} continue {
undef $record;
}
在测试条件之前的每次迭代之后执行continue
块。如果您的代码使用next
提前开始下一次迭代,它仍会被调用。如果您不太可能致电next
,那么请将代码简化为
while (defined( $record = $dataFile->getRecord )) {
$LT_DataFile->encode($record);
undef $record;
}
也可以。