.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "failures 3pm" .TH failures 3pm "2014-07-14" "perl v5.18.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" failures \- Minimalist exception hierarchy generator .SH "VERSION" .IX Header "VERSION" version 0.004 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use failures qw/io::file io::network/; \& use Try::Tiny; \& use Safe::Isa; # for $_isa \& \& try { \& process_file or \& failure::io::file\->throw("oops, something bad happened: $!"); \& } \& catch { \& if ( $_\->$_isa("failure::io::file") ) { \& ... \& } \& elsif( $_\->$_isa("failure::io") ) { \& ... \& } \& elsif( $_\->$_isa("failure") ) { \& ... \& } \& else { \& ... \& } \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module lets you define an exception hierarchy quickly and simply. .PP Here were my design goals: .IP "\(bu" 4 minimalist interface .IP "\(bu" 4 80% of features in 20% of lines of code .IP "\(bu" 4 depend only on core modules (nearly achieved) .IP "\(bu" 4 support hierarchical error types .IP "\(bu" 4 identify errors types by name (class) not by parsing strings .IP "\(bu" 4 leave (possibly expensive) trace decisions to the thrower .PP Currently, \f(CW\*(C`failures\*(C'\fR is implemented in under 70 lines of code. .PP Failure objects are implemented with Class::Tiny to allow easy subclassing (see custom::failures), but \f(CW\*(C`Class::Tiny\*(C'\fR only requires core modules, so other than that exception, the 'core only' goal is achieved. .SH "USAGE" .IX Header "USAGE" .SS "Defining failure categories" .IX Subsection "Defining failure categories" .Vb 1 \& use failures qw/foo::bar foo::baz/; .Ve .PP This will define the following classes in the \f(CW\*(C`failure\*(C'\fR namespace: .IP "\(bu" 4 \&\f(CW\*(C`failure\*(C'\fR .IP "\(bu" 4 \&\f(CW\*(C`failure::foo\*(C'\fR .IP "\(bu" 4 \&\f(CW\*(C`failure::foo::bar\*(C'\fR .IP "\(bu" 4 \&\f(CW\*(C`failure::foo::baz\*(C'\fR .PP Subclasses inherit, so \f(CW\*(C`failure::foo::bar\*(C'\fR is-a \f(CW\*(C`failure::foo\*(C'\fR and \&\f(CW\*(C`failure::foo\*(C'\fR is-a \f(CW\*(C`failure\*(C'\fR. .SS "Attributes" .IX Subsection "Attributes" A failure class has three attributes: \f(CW\*(C`msg\*(C'\fR, \f(CW\*(C`payload\*(C'\fR, and \f(CW\*(C`trace\*(C'\fR. Their usage is described below. Accessors exist for all three. .SS "Throwing failures" .IX Subsection "Throwing failures" The \f(CW\*(C`throw\*(C'\fR method of a failure class takes a single, optional argument that modifies how failure objects are stringified. .PP If no argument is given, a default message is generated if the object is stringified: .PP .Vb 2 \& say failure::foo::bar\->throw; \& # Caught failure::foo::bar .Ve .PP With a single, non-hash-reference argument, the argument is used for the \f(CW\*(C`msg\*(C'\fR attribute and is appended if the object is stringified. .PP .Vb 2 \& say failure::foo::bar\->throw("Ouch!"); \& # Caught failure::foo::bar: Ouch! .Ve .PP With a hash reference argument, the \f(CW\*(C`msg\*(C'\fR key provides the string to append to the default error. If you have extra data to attach to the exception, use the \&\f(CW\*(C`payload\*(C'\fR key: .PP .Vb 4 \& failure::foo::bar\->throw({ \& msg => "Ouch!", \& payload => $extra_data, \& }); .Ve .PP If an optional \f(CW\*(C`trace\*(C'\fR key is provided, it is appended if the object is stringified. To loosely emulate \f(CW\*(C`die\*(C'\fR and provide a simple filename and line number, use the \f(CW\*(C`failure\->line_trace\*(C'\fR class method: .PP .Vb 4 \& failure::foo::bar\->throw({ \& msg => "Ouch!", \& trace => failure\->line_trace, \& }); \& \& # Caught failure::foo::bar: Ouch! \& # \& # Failure caught at line .Ve .PP To provide a trace just like the Carp module (including respecting \f(CW@CARP_NOT\fR) use the \f(CW\*(C`croak_trace\*(C'\fR or \f(CW\*(C`confess_trace\*(C'\fR class methods: .PP .Vb 4 \& failure::foo::bar\->throw({ \& msg => "Ouch!", \& trace => failure\->croak_trace, \& }); \& \& # Caught failure::foo::bar: Ouch! \& # \& # Failure caught at line \& \& failure::foo::bar\->throw({ \& msg => "Ouch!", \& trace => failure\->confess_trace, \& }); \& \& # Caught failure::foo::bar: Ouch! \& # \& # Failure caught at line \& # [confess stack trace continues] .Ve .PP You can provide a \f(CW\*(C`trace\*(C'\fR key with any object that overrides stringification, like Devel::StackTrace: .PP .Vb 4 \& failure::foo::bar\->throw({ \& msg => "Ouch!", \& trace => Devel::StackTrace\->new, \& }); \& \& # Caught failure::foo::bar: Ouch! \& # \& # [stringified Devel::StackTrace object] .Ve .SS "Catching failures" .IX Subsection "Catching failures" Use Try::Tiny, of course. Within a catch block, you know that \f(CW$_\fR is defined, but it still might be an unblessed reference or something that is risky to call \f(CW\*(C`isa\*(C'\fR on. If you load Safe::Isa, you get a code reference in \f(CW$_isa\fR that calls \f(CW\*(C`isa\*(C'\fR only on objects. .PP So catching looks like this: .PP .Vb 2 \& use Try::Tiny; \& use Safe::Isa; \& \& try { ... } \& catch { \& if ( $_\->$_isa("failure::foo") ) { \& # handle it \& } \& }; .Ve .PP If you need to rethrow the exception, just use \f(CW\*(C`die\*(C'\fR: .PP .Vb 3 \& elsif ( $_\->$_isa("failure") ) { \& die $_; \& } .Ve .SS "Overriding failure class behavior" .IX Subsection "Overriding failure class behavior" See custom::failures. .SH "SEE ALSO" .IX Header "SEE ALSO" There are many error/exception systems on \s-1CPAN. \s0 This one is designed to be minimalist. .PP If you have more complex or substantial needs, people I know and trust seem to be recommending: .IP "\(bu" 4 Throwable X exceptions as a Moo/Moose role .IP "\(bu" 4 Throwable::X X Throwable extended with extra goodies .PP Here are other modules I found that weren't appropriate for my needs or didn't suit my taste: .IP "\(bu" 4 Class::Throwable X no hierarchy and always builds a full stack trace .IP "\(bu" 4 Error::Tiny X blends Try::Tiny and a trivial exception base class .IP "\(bu" 4 Exception::Base X complexity on par with Exception::Class, but highly optimized for speed .IP "\(bu" 4 Exception::Class X once highly recommended, but even the author now suggests Throwable .IP "\(bu" 4 Exception::Simple X very simple, but always uses \f(CW\*(C`caller\*(C'\fR and has no hierarchy .IP "\(bu" 4 Exception::Tiny X not bad, but always uses \f(CW\*(C`caller\*(C'\fR and setting up a hierarchy requires extra work .IP "\(bu" 4 Ouch X simple, well-thought out, but no hierarchy; also cutesy function names .PP Here are some that I'm very dubious about: .IP "\(bu" 4 Err X alpha since 2012 .IP "\(bu" 4 Error X no longer recommended by maintainer .IP "\(bu" 4 errors X \*(L"still under design\*(R" since 2009 .IP "\(bu" 4 Exception X dates back to 1996 and undocumented .SH "SUPPORT" .IX Header "SUPPORT" .SS "Bugs / Feature Requests" .IX Subsection "Bugs / Feature Requests" Please report any bugs or feature requests through the issue tracker at . You will be notified automatically of any progress on your issue. .SS "Source Code" .IX Subsection "Source Code" This is open source software. The code repository is available for public review and contribution under the terms of the license. .PP .PP .Vb 1 \& git clone https://github.com/dagolden/failures.git .Ve .SH "AUTHOR" .IX Header "AUTHOR" David Golden .SH "CONTRIBUTOR" .IX Header "CONTRIBUTOR" Michael Jemmeson .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is Copyright (c) 2013 by David Golden. .PP This is free software, licensed under: .PP .Vb 1 \& The Apache License, Version 2.0, January 2004 .Ve