这两种方式中的一种是否必须首选,还是仅仅是品味问题?
#!/usr/bin/env perl
use warnings;
use strict;
use DBI;
my $db = 'sqlite_db';
#################### A ####################
sub get_database_handle {
my ( $db ) = @_;
my $dbh;
eval {
$dbh = DBI->connect( "DBI:SQLite:$db", '', '', {...} )
or die DBI->errstr;
};
if ( $@ ) {
print $@;
return;
}
return $dbh;
}
DATABASES: while ( 1 ) {
# choose a database from a list of databases
# ...
my $dbh = get_database_handle( $db );
next DATABASES if not defined $dbh;
# ...
# do something with the database
}
#################### B ####################
sub get_database_handle {
my ( $db ) = @_;
my $dbh = DBI->connect( "DBI:SQLite:$db", '', '', {...} )
or die DBI->errstr;
return $dbh;
}
DATABASES: while ( 1 ) {
# choose a database from a list of databases
# ...
my $dbh;
eval { $dbh = get_database_handle( $db ); };
if ( $@ ) {
print $@;
next DATABASES;
}
# ...
# do something with the database
}
答案 0 :(得分:3)
为什么要评估?当你无法获得数据库句柄时,你打算做什么?
至少,子程序应该返回一个数据库句柄或者死掉,所以那里没有eval。
如果在数据库错误时确实有一些工作要做,那么在子程序之外进行eval。对于您的错误处理逻辑,仅在子例程周围不一定可能是更宽的范围。
但如果你想要的只是终止程序并输出错误,那就让异常冒泡。
答案 1 :(得分:2)
这取决于在项目其余部分处理错误的首选方式。
如果您打算使用例外,请让您的函数抛出它们。
如果您要通过条件手动处理错误,请不要抛出(eval inside)。
我自己更喜欢例外。它们很响亮(你知道有些东西坏了!),加上通过Carp::confess
/ Carp::longmess
和$SIG{__DIE__}
的堆栈跟踪在大型代码库的情况下是一个很好的奖励。
这是一个(非)成功的故事。一两个月前,我们推出了破坏的代码,由于来自DB处理函数的未经检查的返回值而导致数据无声地损坏。它正在生产一天。恢复数据是一个痛苦的世界。
答案 2 :(得分:2)
如果您的代码看起来像那样,那么完全使用RaiseError => 1
是没有意义的。如果您想保留该代码布局,请改用RaiseError => 0
。 (您可以随后使用$ dbh-> {RaiseError} = 1;`来启用它。)
sub get_database_handle {
my ( $db ) = @_;
return DBI->connect("DBI:SQLite:$db", '', '', {
...
RaiseError => 0,
PrintError => 1,
});
}
for my $db ( ... ) {
my $dbh = get_database_handle( $db )
or next;
...
}
那就是说,我建议你继续使用RaiseError => 1
,但是你改变了你的代码布局。具体来说,您应该扩大评估的范围。
sub get_database_handle {
my ( $db ) = @_;
return DBI->connect("DBI:SQLite:$db", '', '', {
...
RaiseError => 1,
PrintError => 0,
});
}
for my $db ( ... ) {
if (!eval {
my $dbh = get_database_handle( $db );
...
1 # No exception
}) {
warn("Error processing database $db: $@");
}
}
这将捕获任何错误,而不仅仅是数据库连接错误。