-
-
14 Jul 2014 19:44:32 UTC
- Distribution: failures
- Module version: 0.004
- Source (raw)
- Browse (raw)
- Changes
- Homepage
- How to Contribute
- Repository
- Issues
- Testers (4877 / 0 / 3)
- Kwalitee
Bus factor: 1- 100.00% Coverage
- License: apache_2_0
- Perl: v5.8.1
- Activity
24 month- Tools
- Download (19.19KB)
- MetaCPAN Explorer
- Permissions
- Subscribe to distribution
- Permalinks
- This version
- Latest version
NAME
custom::failures - Minimalist, customized exception hierarchy generator
VERSION
version 0.004
SYNOPSIS
package MyApp::failure; use custom::failures qw/io::file io::network/; # customize failure methods…
DESCRIPTION
This module works like failures but lets you define a customized exception hierarchy if you need a custom namespace, additional attributes, or customized object behaviors.
Because failure classes have an
@ISA
chain and Perl by default uses depth-first-search to resolve method calls, you can override behavior anywhere in the custom hierarchy and it will take precedence over defaultfailure
behaviors.There are two methods that might be useful to override:
message
throw
Both are described further, below.
USAGE
Defining a custom failure hierarchy
package MyApp::failure; use custom::failures qw/foo::bar/;
This will define a failure class hierarchy under the calling package's namespace. The following diagram show the classes that will be created (arrows denote 'is-a' relationships):
MyApp::failure::foo::bar --> failure::foo::bar | | V V MyApp::failure::foo --> failure::foo | | V V MyApp::failure --> failure
Alternatively, if you want a different namespace for the hierarchy, do it this way:
use custom::failures 'MyApp::Error' => [ 'foo::bar' ];
That will create the following classes and relationships:
MyApp::Error::foo::bar --> failure::foo::bar | | V V MyApp::Error::foo --> failure::foo | | V V MyApp::Error --> failure
By having custom classes also inherit from a standard namespace, you can throw a custom error class that will still be caught in the standard namespace:
use Safe::Isa; # for $_isa try { MyApp::failure::foo::bar->throw; } catch { if ( $_->$_isa( "failure::foo" ) ) { # handle it here } };
Adding custom attributes
Failure classes are implemented with Class::Tiny, so adding attributes is trivially easy:
package MyApp::failure; use custom::failures qw/foo::bar/; use Class::Tiny qw/user/;
This adds a
user
attribute toMyApp::failure
and all its subclasses so it can be set in the argument tothrow
:MyApp::failure::foo->throw( { msg => "Ouch!", user => "me" } );
Be sure to load
Class::Tiny
after you loadcustom::failures
so that your@ISA
is already set up.Overriding the
message
methodOverriding
message
lets you modify how the error string is produced. Themessage
method takes a string (typically just themsg
field) and returns a string. It should not produce or append stack trace information. That is done during object stringification.Call
SUPER::message
if you want the standard error text prepended ("Caught $class: ..."
).For example, if you want to use String::Flogger to render messages:
package MyApp::failure; use custom::failures qw/foo::bar/; use String::Flogger qw/flog/; sub message { my ( $self, $msg ) = @_; return $self->SUPER::message( flog($msg) ); }
Then you can pass strings or array references or code references as the
msg
forthrow
:MyApp::failure->throw( "just a string" ); MyApp::failure->throw( [ "show some data %s", $ref ] ); MyApp::failure->throw( sub { call_expensive_sub() } );
Because the
message
method is only called during stringification (unless you call it yourself), the failure class type can be checked before any expensive rendering is done.Overriding the
throw
methodOverriding
throw
lets you modify the arguments you can provide or ensure that a trace is included. It can take whatever arguments you want and should callSUPER::throw
with a hash reference to actually throw the error.For example, to capture the filename associated with file errors:
package MyApp::failure; use custom::failures qw/file/; use Class::Tiny qw/filename/; sub throw { my ( $class, $msg, $file ) = @_; my $args = { msg => $msg, filename => $file, trace => failures->croak_trace, }; $self->SUPER::throw( $args ); } sub message { # do something with 'msg' and 'filename' }
Later you could use it like this:
MyApp::failure::file->throw( opening => $some_file );
Using BUILD
Class::Tiny
supportsBUILD
, so you can also use that to do things with failure objects when thrown. This example logs exceptions as they are built:use Log::Any qw/$log/; sub BUILD { my ($self) = @_; $log->error( $self->message ); }
By using
message
instead of stringifying$self
, we log the message but not the trace (if any).AUTHOR
David Golden <dagolden@cpan.org>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2013 by David Golden.
This is free software, licensed under:
The Apache License, Version 2.0, January 2004
Module Install Instructions
To install failure, copy and paste the appropriate command in to your terminal.
cpanm failure
perl -MCPAN -e shell install failure
For more information on module installation, please visit the detailed CPAN module installation guide.