File Coverage

blib/lib/X/Tiny.pm
Criterion Covered Total %
statement 20 20 100.0
branch 2 2 100.0
condition n/a
subroutine 6 6 100.0
pod 1 1 100.0
total 29 29 100.0


line stmt bran cond sub pod time code
1             package X::Tiny;
2              
3 2     2   29225 use strict;
  2         2  
  2         47  
4 2     2   7 use warnings;
  2         2  
  2         91  
5              
6             our $VERSION = '0.01-TRIAL';
7              
8             =encoding utf-8
9              
10             =head1 NAME
11              
12             X::Tiny - Base class for a bare-bones exception factory
13              
14             =head1 SYNOPSIS
15              
16             package My::Module::X;
17              
18             use parent qw( X::Tiny );
19              
20             #----------------------------------------------------------------------
21              
22             package My::Module::X::Base;
23              
24             use parent qw( X::Tiny::Base );
25              
26             #----------------------------------------------------------------------
27              
28             package My::Module::X::IO;
29              
30             use parent qw( My::Module::X::Base );
31              
32             #----------------------------------------------------------------------
33              
34             package My::Module::X::Blah;
35              
36             use parent qw( My::Module::X::Base );
37              
38             sub _new {
39             my ($class, @args) = @_;
40              
41             my $self = $class->SUPER::_new('Blah blah, @args);
42              
43             return bless $self, $class;
44             }
45              
46             #----------------------------------------------------------------------
47              
48             package main;
49              
50             local $@; #always!
51             eval {
52             die My::Module::X->create('IO', 'The message', key1 => val1, … );
53             };
54              
55             if ( my $err = $@ ) {
56             print $err->get('key1');
57             }
58              
59             =head1 DESCRIPTION
60              
61             This stripped-down exception framework provides a baseline
62             of functionality for distributions that want to expose exception
63             hierarchies with minimal fuss. It’s a pattern that I implemented in some
64             other distributions I created and didn’t want to copy/paste around.
65              
66             =head1 BENEFITS OF EXCEPTIONS
67              
68             Exceptions are better for error reporting in Perl than the
69             C-style “return in failure” pattern. In brief,
70             you should use exceptions because they are a logical, natural way to report
71             failures: if you’re given a set of instructions, and something goes wrong
72             in one of those instructions, it makes sense to stop and go back to see what
73             to do in response to the problem.
74              
75             Perl’s built-ins unwisely make the caller responsibile for error checking—as
76             a result of which much Perl code fails to check for failures from those
77             built-ins, which makes for far more difficult debugging when some code down
78             the line just mysteriously produces an unexpected result.
79             The more sensible pattern is for an exception to be thrown at the spot where
80             the error occurred.
81              
82             Perl’s default exceptions are just scalars. A more useful pattern is to throw
83             exception objects whose type and attributes can facilitate meaningful
84             error checking; for example, you may not care if a call to C fails
85             with C, so you can just ignore that failure. Or, you might care, but
86             you might prefer just to C rather than to stop what you’re doing.
87             That’s where C comes in.
88              
89             =head1 FEATURES
90              
91             =over
92              
93             =item * Super-lightweight: No exceptions are loaded until they’re needed.
94              
95             =item * Simple, flexible API
96              
97             =item * String overload with stack trace
98              
99             =item * Minimal code necessary
100              
101             =back
102              
103             =head1 USAGE
104              
105             You’ll first create a factory class that subclasses C.
106             (In the SYNOPSIS’s example, this module is C.) All of your
107             exceptions B exist under that factory class’s namespace.
108              
109             You’ll then create a base exception class for your distribution.
110             In the SYNOPSIS’s example, this module is C.
111             Your distribution’s other exceptions should all subclass this one.
112              
113             =head1 METHODS
114              
115             There’s only one method in the factory class:
116              
117             =head2 I->create( TYPE, ARG1, ARG2, .. )
118              
119             To create an exception, call the C method of your factory class.
120             This will load the exception class if it’s not already in memory.
121             The TYPE you pass in is equivalent to the exception class’s module name but
122             with the factory class’s name chopped off the left part. So, if you call:
123              
124             My::Module::X->create('BadInput', 'foo', 'bar')
125              
126             … this will instantiate and return an instance of C,
127             with the arguments C and C.
128              
129             =head1 EXCEPTION OBJECTS
130              
131             See C for more information about the features that that
132             module exposes to subclasses.
133              
134             =head1 DESIGN CONSIDERATIONS
135              
136             Admittedly, the lazy-loading behavior here embodies a generally-unwise
137             practice of doing failure-prone work in the process of reporting a failure.
138             In my own experience, though, that’s a reasonable tradeoff for the
139             expressiveness of typed exceptions.
140              
141             Do be sure that any failure-prone work you do as part of exception
142             instantiation has its own failure-checking mechanism. There really are not
143             meant to be “sub-failures” here.
144              
145             =cut
146              
147 2     2   8 use strict;
  2         5  
  2         42  
148 2     2   6 use warnings;
  2         3  
  2         52  
149              
150 2     2   892 use Module::Load ();
  2         1962  
  2         167  
151              
152             sub create {
153 5     5 1 868 my ( $class, $type, @args ) = @_;
154              
155 5         11 my $x_package = "${class}::$type";
156              
157 5 100       38 if (!$x_package->can('new')) {
158 1         5 Module::Load::load($x_package);
159             }
160              
161 5         138 return $x_package->new(@args);
162             }
163              
164             1;
165              
166             #----------------------------------------------------------------------
167              
168             =head1 REPOSITORY
169              
170             https://github.com/FGasper/p5-X-Tiny
171              
172             =head1 AUTHOR
173              
174             Felipe Gasper (FELIPE)