2013年02月13日

I wrote too easy exception interface module.
https://metacpan.org/release/Exception-Tiny

既存の例外処理モジュールは、結構頑張ってるのが多くてドキュメント凄いいっぱいあったり実装が読みにくかったり痒い所がかけないので、おばあちゃんの孫の手的な実装をリリースしました。

例外処理に最低限必要な実装しか無いので使うのが簡単です。
例外クラスにアクセサを生やしたければ、お好きなアクセサーで生やすもよいし、例外の階層構造作りたければ普通に use parent すればいいし、既存の実装を変えたければ user parent 'Exception::Tiny'; で継承された側のモジュールでメソッドを上書きすればいいです。

Exception::Tiny 本体のお約束はなくて、普通に Perl のルールさえ知ってれば好きな例外処理を書けるのでとっても簡単ですね!

例えば以下のようにテラカンタンに書けます。

use strict;
use warnings;
use lib 'lib';
use 5.012;

package IOException;
use parent 'Exception::Tiny';
use Class::Accessor::Lite (
    ro => [qw/ fh /],
);

package FileException;
use parent -norequire, 'IOException';
use Class::Accessor::Lite (
    ro => [qw/ filepath /],
);

package NetworkException;
use parent -norequire, 'IOException';

package HTTPException;
use parent -norequire, 'NetworkException';
use Class::Accessor::Lite (
    ro => [qw/ uri code /],
);

sub as_string {
    my $self = shift;
    sprintf "HTTPException: message=%s, fh=%s, code=%s, uri=%s\n", $self->message, $self->fh, $self->code, $self->uri;
}

package OtherException;
use parent 'Exception::Tiny';

package RethrowException;
use parent 'Exception::Tiny';

package main;


sub exception (&) {
    my $cb = shift;
    eval { $cb->() };

    given ($@) {
        when (HTTPException->caught($_)) {
            warn "$_\n";
        }
        when (IOException->caught($_)) {
            printf STDERR "fh=%s\n", $_->fh;
            warn "$_\n";
            warn "-----------------------\n";
        }
        when (RethrowException->caught($_)) {
            $_->rethrow;
        }
        when (Exception::Tiny->caught($_)) {
            warn "$_\n";
            warn "-----------------------\n";
        }
        default {
            warn "$@\n";
            warn "-----------------------\n";
        }
    }
}

exception {
    die 'normal die';
};

exception {
    FileException->throw(
        filepath => '/foo/bar',
        fh       => 'FILE HANDLE',
    );
};

exception {
    HTTPException->throw(
        message => 'not found',
        code    => '404',
        uri     => 'http://example.com',
        fh      => 'TCP HANDLE',
    );
};

exception {
    OtherException->throw;
};

eval {
    exception {
        RethrowException->throw('rethrow');
    };
};
if (my $e = $@) {
    warn $e if RethrowException->caught($e);
}

__END__
normal die at ./winecall.pl line 69.

-----------------------
fh=FILE HANDLEFileException at ./winecall.pl line 73.
-----------------------
HTTPException: message=not found, fh=TCP HANDLE, code=404, uri=http://example.com
OtherException at ./winecall.pl line 89.
-----------------------
rethrow at ./winecall.pl line 94. at ./winecall.pl line 98.

happy exception!

Posted by Yappo at 2013年02月13日 13:03 | TrackBack | Perl
Comments
Post a comment









Remember personal info?






コメントを投稿する前に↓の場所にnospamと入力してください。