File Coverage

blib/lib/Object/Tiny.pm
Criterion Covered Total %
statement 18 18 100.0
branch 5 8 62.5
condition 3 6 50.0
subroutine 6 6 100.0
pod 0 1 0.0
total 32 39 82.0


line stmt bran cond sub pod time code
1             package Object::Tiny;
2              
3 3     3   3587 use strict 'vars', 'subs';
  3         6  
  3         130  
4             BEGIN {
5 3     3   73 require 5.004;
6 3         746 $Object::Tiny::VERSION = '1.08';
7             }
8              
9             sub import {
10 3 50   3   488 return unless shift eq 'Object::Tiny';
11 3         5 my $pkg = caller;
12 3         5 my $child = !! @{"${pkg}::ISA"};
  3         16  
13 5 100 33     64 eval join "\n",
      66        
14             "package $pkg;",
15             ($child ? () : "\@${pkg}::ISA = 'Object::Tiny';"),
16             map {
17 3 50   2   12 defined and ! ref and /^[^\W\d]\w*\z/s
  2     2   12  
  2         4959  
18             or die "Invalid accessor name '$_'";
19 4         194 "sub $_ { return \$_[0]->{$_} }"
20             } @_;
21 2 50       8 die "Failed to generate $pkg" if $@;
22 2         27 return 1;
23             }
24              
25             sub new {
26 2     2 0 2000 my $class = shift;
27 2         9 bless { @_ }, $class;
28             }
29              
30             1;
31              
32             __END__
33              
34             =pod
35              
36             =head1 NAME
37              
38             Object::Tiny - Class building as simple as it gets
39              
40             =head1 SYNOPSIS
41              
42             # Define a class
43             package Foo;
44            
45             use Object::Tiny qw{ bar baz };
46            
47             1;
48            
49            
50             # Use the class
51             my $object = Foo->new( bar => 1 );
52            
53             print "bar is " . $object->bar . "\n";
54              
55             =head1 DESCRIPTION
56              
57             There's a whole bunch of class builders out there. In fact, creating
58             a class builder seems to be something of a rite of passage (this is
59             my fifth, at least).
60              
61             Unfortunately, most of the time I want a class builder I'm in a
62             hurry and sketching out lots of fairly simple data classes with fairly
63             simple structure, mostly just read-only accessors, and that's about it.
64              
65             Often this is for code that won't end up on CPAN, so adding a small
66             dependency doesn't matter much. I just want to be able to define these
67             classes FAST.
68              
69             By which I mean LESS typing than writing them by hand, not more. And
70             I don't need all those weird complex features that bloat out the code
71             and take over the whole way I build modules.
72              
73             And so, I present yet another member of the Tiny family of modules,
74             Object::Tiny.
75              
76             The goal here is really just to save me some typing. There's others
77             that could do the job just fine, but I want something that does as little
78             as possible and creates code the same way I'd have written it by hand
79             anyway.
80              
81             To use Object::Tiny, just call it with a list of accessors to be created.
82              
83             use Object::Tiny 'foo', 'bar';
84              
85             For a large list, I lay it out like this...
86              
87             use Object::Tiny qw{
88             item_font_face
89             item_font_color
90             item_font_size
91             item_text_content
92             item_display_time
93             seperator_font_face
94             seperator_font_color
95             seperator_font_size
96             seperator_text_content
97             };
98              
99             This will create a bunch of simple accessors, and set the inheritance to
100             be the child of Object::Tiny.
101              
102             Object::Tiny is empty other than a basic C<new> constructor which
103             does the following
104              
105             sub new {
106             my $class = shift;
107             return bless { @_ }, $class;
108             }
109              
110             In fact, if doing the following in your class gets annoying...
111              
112             sub new {
113             my $class = shift;
114             my $self = $class->SUPER::new( @_ );
115            
116             # Extra checking and such
117             ...
118            
119             return $self;
120             }
121              
122             ... then feel free to ditch the SUPER call and just create the hash
123             yourself! It's not going to make a lick of different and there's nothing
124             magic going on under the covers you might break.
125              
126             And that's really all there is to it. Let a million simple data classes
127             bloom. Features? We don't need no stinking features.
128              
129             =head2 Handling Subclasses
130              
131             If the class you are using Object::Tiny for is already a subclass of
132             another Object::Tiny class (or a subclass of anything else) it doesn't
133             really work to make the class use multiple inheritance.
134              
135             So in this case, Object::Tiny will create the accessors you specify, but
136             WON'T make it a subclass of Object::Tiny.
137              
138             =head2 Why bother when Class::Accessor::* already does the same thing?
139              
140             As a class builder, L<Object::Tiny> inevitably is compared to
141             L<Class::Accessor> and related modules. They seem so similar, so why would
142             I reimplement it?
143              
144             The answer is that for experienced developers that don't need or want
145             hand-holding, Object::Tiny is just outright better, faster or cheaper
146             on every single metric than L<Class::Accessor::Fast>, which
147             is the most comparable member of the Class::Accessor::* family.
148              
149             B<Object::Tiny is 93% smaller than Class::Accessor::Fast>
150              
151             L<Class::Accessor::Fast> requires about 125k of memory to load.
152              
153             Object::Tiny requires about 8k of memory to load.
154              
155             B<Object::Tiny is 75% more terse to use than Class::Accessor::Fast>
156              
157             Object::Tiny is used with the least possible number of keystrokes
158             (short of making the actual name Object::Tiny smaller).
159              
160             And it requires no ugly constructor methods.
161              
162             I mean really, what sort of a method name is 'mk_ro_accessors'. That sort
163             of thing went out of style in the early nineties.
164              
165             Using Class::Accessor::Fast...
166              
167             package Foo::Bar;
168             use base 'Class::Accessor::Fast';
169             Foo::Bar->mk_ro_accessors(qw{ foo bar baz });
170              
171             Using Object::Tiny...
172              
173             package Foo::Bar;
174             use Object::Tiny qw{ foo bar baz };
175              
176             Further, Object::Tiny lets you pass your params in directly, without
177             having to wrap them in an additional HASH reference that will just be
178             copied ANYWAY inside the constructor.
179              
180             Using Class::Accessor::Fast...
181              
182             my $object = Foo::Bar->new( {
183             foo => 1,
184             bar => 2,
185             baz => 3,
186             } );
187              
188             Using Object::Tiny...
189              
190             my $object = Foo::Bar->new(
191             foo => 1,
192             bar => 2,
193             baz => 3,
194             );
195              
196             B<Object::Tiny constructors are 110% faster than Class::Accessor::Fast>
197              
198             Object::Tiny accessors are identical in speed to Class::Accessor::Fast
199             accessors, but Object::Tiny constructors are TWICE as fast as
200             Class::Accessor::Fast constructors, DESPITE C:A:Fast forcing you to pass
201             by reference (which is typically done for speed reasons).
202              
203             Benchmarking constructor plus accessors...
204             Rate accessor tiny
205             accessor 100949/s -- -45%
206             tiny 182382/s 81% --
207            
208             Benchmarking constructor alone...
209             Rate accessor tiny
210             accessor 156470/s -- -54%
211             tiny 342231/s 119% --
212            
213             Benchmarking accessors alone...
214             Rate tiny accessor
215             tiny 81.0/s -- -0%
216             accessor 81.0/s 0% --
217              
218             B<Object::Tiny pollutes your API 95% less than Class::Accessor::Fast>
219              
220             Object::Tiny adds two methods to your class, C<new> and C<import>. The
221             C<new> constructor is so trivial you can just ignore it and use your own
222             if you wish, and the C<import> will shortcut and do nothing (it is used to
223             implement the C<"use Object::Tiny qw{ foo bar baz };"> syntax itself).
224              
225             So if you make your own import, you can ignore the Object::Tiny one.
226              
227             Class::Accessor::Fast isn't quite as light, adding all sorts of useless
228             extra public methods (why on earth would you want to add method accessors
229             at run-time?).
230              
231             Here's what the classes used in the benchmark end up like.
232              
233             DB<1> use Class::Inspector
234            
235             DB<2> x Class::Inspector->methods('Foo_Bar_Tiny');
236             0 ARRAY(0xfda780)
237             0 'bar'
238             1 'baz'
239             2 'foo'
240             3 'import'
241             4 'new'
242            
243             DB<3> x Class::Inspector->methods('Foo_Bar_Accessor');
244             0 ARRAY(0xfdb3c8)
245             0 '_bar_accessor'
246             1 '_baz_accessor'
247             2 '_carp'
248             3 '_croak'
249             4 '_foo_accessor'
250             5 '_mk_accessors'
251             6 'accessor_name_for'
252             7 'bar'
253             8 'baz'
254             9 'best_practice_accessor_name_for'
255             10 'best_practice_mutator_name_for'
256             11 'follow_best_practice'
257             12 'foo'
258             13 'get'
259             14 'make_accessor'
260             15 'make_ro_accessor'
261             16 'make_wo_accessor'
262             17 'mk_accessors'
263             18 'mk_ro_accessors'
264             19 'mk_wo_accessors'
265             20 'mutator_name_for'
266             21 'new'
267             22 'set'
268              
269             As you can see, Object::Tiny adds 2 methods to your class, Class::Accessor
270             adds 16 methods, plus one extra one for every accessor.
271              
272             B<Object::Tiny doesn't have any of the caveats of Class::Accessor::Fast>
273              
274             When you call B<use Object::Tiny qw{ foo bar baz }> it isn't treated as some
275             sort of specification for the class, it's just a list of accessors you want
276             made for you.
277              
278             So if you want to customize C<foo> you don't need to get into contortions with
279             "pure" base classes or calling alternate internal methods. Just make your own
280             C<foo> method and remove C<foo> from the list passed to the C<use> call.
281              
282             B<Object::Tiny is more back-compatible than Class::Accessor::Fast>
283              
284             Class::Accessor::Fast has a minimum Perl dependency of 5.005002.
285              
286             Object::Tiny has a minimum Perl dependency of 5.004.
287              
288             B<Object::Tiny has no module dependencies whatsoever>
289              
290             Object::Tiny does not load ANYTHING at all outside of its own single .pm file.
291              
292             So Object::Tiny will never get confused in odd situations due to old or weird
293             versions of other modules (Class::Accessor::Fast has a dependency on base.pm,
294             which has some caveats of its own).
295              
296             =head1 SUPPORT
297              
298             Bugs should be reported via the CPAN bug tracker at
299              
300             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Object-Tiny>
301              
302             For other issues, contact the author.
303              
304             =head1 AUTHOR
305              
306             Adam Kennedy E<lt>adamk@cpan.orgE<gt>
307              
308             =head1 SEE ALSO
309              
310             L<Config::Tiny>
311              
312             =head1 COPYRIGHT
313              
314             Copyright 2007 - 2011 Adam Kennedy.
315              
316             This program is free software; you can redistribute
317             it and/or modify it under the same terms as Perl itself.
318              
319             The full text of the license can be found in the
320             LICENSE file included with this module.
321              
322             =cut