1

これら 2 つの方法のいずれかを優先する必要がありますか、それとも単に好みの問題ですか?

#!/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
}
4

3 に答える 3

3

なぜまったく評価するのですか?データベース ハンドルを取得できない場合はどうしますか?

少なくとも、サブルーチンはデータベース ハンドルを返すか終了する必要があるため、そこには eval はありません。

データベース エラーが発生したときに何か生産的なことを行う必要がある場合は、サブルーチンの外で eval を実行します。サブルーチンだけでは必要ありませんが、エラー処理ロジックに応じて、さらに広い範囲になる可能性があります。

しかし、プログラムを終了してエラーを出力することだけが必要な場合は、例外をバブルアップさせてください。

于 2012-09-28T07:30:00.837 に答える
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: $@");
    }
}

これにより、データベース接続エラーだけでなく、すべてのエラーがキャッチされます。

于 2012-09-28T08:13:52.437 に答える
2

それは、プロジェクトの残りの部分で優先されるエラー処理方法によって異なります。

  • 例外を使用する予定がある場合は、関数に例外をスローさせます。

  • 条件を介して手動でエラーを処理する場合は、スローしないでください (eval inside)。

私自身は例外を好みます。それらは大声で (何かが壊れていることがわかります!)、さらにCarp::confess/Carp::longmessを介したスタック トレース$SIG{__DIE__}があり、大きなコードベースの場合には素晴らしいボーナスです。

ここに(不)成功の話があります。1 ~ 2 か月前に、DB 処理関数からのチェックされていない戻り値が原因で、暗黙のうちにデータが破損する壊れたコードをロールアウトしました。一日制作中でした。データの復活は苦痛の世界でした。

于 2012-09-28T08:08:35.757 に答える