Initial Commit
This commit is contained in:
320
database/perl/vendor/lib/Object/Tiny.pm
vendored
Normal file
320
database/perl/vendor/lib/Object/Tiny.pm
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
package Object::Tiny; # git description: 5abde2e
|
||||
|
||||
use strict 'vars', 'subs';
|
||||
|
||||
our $VERSION = '1.09';
|
||||
|
||||
sub import {
|
||||
return unless shift eq 'Object::Tiny';
|
||||
my $pkg = caller;
|
||||
my $child = !! @{"${pkg}::ISA"};
|
||||
eval join "\n",
|
||||
"package $pkg;",
|
||||
($child ? () : "\@${pkg}::ISA = 'Object::Tiny';"),
|
||||
map {
|
||||
defined and ! ref and /^[^\W\d]\w*\z/s
|
||||
or die "Invalid accessor name '$_'";
|
||||
"sub $_ { return \$_[0]->{$_} }"
|
||||
} @_;
|
||||
die "Failed to generate $pkg" if $@;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
bless { @_ }, $class;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Object::Tiny - Class building as simple as it gets
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Define a class
|
||||
package Foo;
|
||||
|
||||
use Object::Tiny qw{ bar baz };
|
||||
|
||||
1;
|
||||
|
||||
|
||||
# Use the class
|
||||
my $object = Foo->new( bar => 1 );
|
||||
|
||||
print "bar is " . $object->bar . "\n";
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There's a whole bunch of class builders out there. In fact, creating
|
||||
a class builder seems to be something of a rite of passage (this is
|
||||
my fifth, at least).
|
||||
|
||||
Unfortunately, most of the time I want a class builder I'm in a
|
||||
hurry and sketching out lots of fairly simple data classes with fairly
|
||||
simple structure, mostly just read-only accessors, and that's about it.
|
||||
|
||||
Often this is for code that won't end up on CPAN, so adding a small
|
||||
dependency doesn't matter much. I just want to be able to define these
|
||||
classes FAST.
|
||||
|
||||
By which I mean LESS typing than writing them by hand, not more. And
|
||||
I don't need all those weird complex features that bloat out the code
|
||||
and take over the whole way I build modules.
|
||||
|
||||
And so, I present yet another member of the Tiny family of modules,
|
||||
Object::Tiny.
|
||||
|
||||
The goal here is really just to save me some typing. There's others
|
||||
that could do the job just fine, but I want something that does as little
|
||||
as possible and creates code the same way I'd have written it by hand
|
||||
anyway.
|
||||
|
||||
To use Object::Tiny, just call it with a list of accessors to be created.
|
||||
|
||||
use Object::Tiny 'foo', 'bar';
|
||||
|
||||
For a large list, I lay it out like this...
|
||||
|
||||
use Object::Tiny qw{
|
||||
item_font_face
|
||||
item_font_color
|
||||
item_font_size
|
||||
item_text_content
|
||||
item_display_time
|
||||
seperator_font_face
|
||||
seperator_font_color
|
||||
seperator_font_size
|
||||
seperator_text_content
|
||||
};
|
||||
|
||||
This will create a bunch of simple accessors, and set the inheritance to
|
||||
be the child of Object::Tiny.
|
||||
|
||||
Object::Tiny is empty other than a basic C<new> constructor which
|
||||
does the following
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
return bless { @_ }, $class;
|
||||
}
|
||||
|
||||
In fact, if doing the following in your class gets annoying...
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = $class->SUPER::new( @_ );
|
||||
|
||||
# Extra checking and such
|
||||
...
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
... then feel free to ditch the SUPER call and just create the hash
|
||||
yourself! It's not going to make a lick of different and there's nothing
|
||||
magic going on under the covers you might break.
|
||||
|
||||
And that's really all there is to it. Let a million simple data classes
|
||||
bloom. Features? We don't need no stinking features.
|
||||
|
||||
=head2 Handling Subclasses
|
||||
|
||||
If the class you are using Object::Tiny for is already a subclass of
|
||||
another Object::Tiny class (or a subclass of anything else) it doesn't
|
||||
really work to make the class use multiple inheritance.
|
||||
|
||||
So in this case, Object::Tiny will create the accessors you specify, but
|
||||
WON'T make it a subclass of Object::Tiny.
|
||||
|
||||
=head2 Why bother when Class::Accessor::* already does the same thing?
|
||||
|
||||
As a class builder, L<Object::Tiny> inevitably is compared to
|
||||
L<Class::Accessor> and related modules. They seem so similar, so why would
|
||||
I reimplement it?
|
||||
|
||||
The answer is that for experienced developers that don't need or want
|
||||
hand-holding, Object::Tiny is just outright better, faster or cheaper
|
||||
on every single metric than L<Class::Accessor::Fast>, which
|
||||
is the most comparable member of the Class::Accessor::* family.
|
||||
|
||||
B<Object::Tiny is 93% smaller than Class::Accessor::Fast>
|
||||
|
||||
L<Class::Accessor::Fast> requires about 125k of memory to load.
|
||||
|
||||
Object::Tiny requires about 8k of memory to load.
|
||||
|
||||
B<Object::Tiny is 75% more terse to use than Class::Accessor::Fast>
|
||||
|
||||
Object::Tiny is used with the least possible number of keystrokes
|
||||
(short of making the actual name Object::Tiny smaller).
|
||||
|
||||
And it requires no ugly constructor methods.
|
||||
|
||||
I mean really, what sort of a method name is 'mk_ro_accessors'. That sort
|
||||
of thing went out of style in the early nineties.
|
||||
|
||||
Using Class::Accessor::Fast...
|
||||
|
||||
package Foo::Bar;
|
||||
use base 'Class::Accessor::Fast';
|
||||
Foo::Bar->mk_ro_accessors(qw{ foo bar baz });
|
||||
|
||||
Using Object::Tiny...
|
||||
|
||||
package Foo::Bar;
|
||||
use Object::Tiny qw{ foo bar baz };
|
||||
|
||||
Further, Object::Tiny lets you pass your params in directly, without
|
||||
having to wrap them in an additional HASH reference that will just be
|
||||
copied ANYWAY inside the constructor.
|
||||
|
||||
Using Class::Accessor::Fast...
|
||||
|
||||
my $object = Foo::Bar->new( {
|
||||
foo => 1,
|
||||
bar => 2,
|
||||
baz => 3,
|
||||
} );
|
||||
|
||||
Using Object::Tiny...
|
||||
|
||||
my $object = Foo::Bar->new(
|
||||
foo => 1,
|
||||
bar => 2,
|
||||
baz => 3,
|
||||
);
|
||||
|
||||
B<Object::Tiny constructors are 110% faster than Class::Accessor::Fast>
|
||||
|
||||
Object::Tiny accessors are identical in speed to Class::Accessor::Fast
|
||||
accessors, but Object::Tiny constructors are TWICE as fast as
|
||||
Class::Accessor::Fast constructors, DESPITE C:A:Fast forcing you to pass
|
||||
by reference (which is typically done for speed reasons).
|
||||
|
||||
Benchmarking constructor plus accessors...
|
||||
Rate accessor tiny
|
||||
accessor 100949/s -- -45%
|
||||
tiny 182382/s 81% --
|
||||
|
||||
Benchmarking constructor alone...
|
||||
Rate accessor tiny
|
||||
accessor 156470/s -- -54%
|
||||
tiny 342231/s 119% --
|
||||
|
||||
Benchmarking accessors alone...
|
||||
Rate tiny accessor
|
||||
tiny 81.0/s -- -0%
|
||||
accessor 81.0/s 0% --
|
||||
|
||||
B<Object::Tiny pollutes your API 95% less than Class::Accessor::Fast>
|
||||
|
||||
Object::Tiny adds two methods to your class, C<new> and C<import>. The
|
||||
C<new> constructor is so trivial you can just ignore it and use your own
|
||||
if you wish, and the C<import> will shortcut and do nothing (it is used to
|
||||
implement the C<"use Object::Tiny qw{ foo bar baz };"> syntax itself).
|
||||
|
||||
So if you make your own import, you can ignore the Object::Tiny one.
|
||||
|
||||
Class::Accessor::Fast isn't quite as light, adding all sorts of useless
|
||||
extra public methods (why on earth would you want to add method accessors
|
||||
at run-time?).
|
||||
|
||||
Here's what the classes used in the benchmark end up like.
|
||||
|
||||
DB<1> use Class::Inspector
|
||||
|
||||
DB<2> x Class::Inspector->methods('Foo_Bar_Tiny');
|
||||
0 ARRAY(0xfda780)
|
||||
0 'bar'
|
||||
1 'baz'
|
||||
2 'foo'
|
||||
3 'import'
|
||||
4 'new'
|
||||
|
||||
DB<3> x Class::Inspector->methods('Foo_Bar_Accessor');
|
||||
0 ARRAY(0xfdb3c8)
|
||||
0 '_bar_accessor'
|
||||
1 '_baz_accessor'
|
||||
2 '_carp'
|
||||
3 '_croak'
|
||||
4 '_foo_accessor'
|
||||
5 '_mk_accessors'
|
||||
6 'accessor_name_for'
|
||||
7 'bar'
|
||||
8 'baz'
|
||||
9 'best_practice_accessor_name_for'
|
||||
10 'best_practice_mutator_name_for'
|
||||
11 'follow_best_practice'
|
||||
12 'foo'
|
||||
13 'get'
|
||||
14 'make_accessor'
|
||||
15 'make_ro_accessor'
|
||||
16 'make_wo_accessor'
|
||||
17 'mk_accessors'
|
||||
18 'mk_ro_accessors'
|
||||
19 'mk_wo_accessors'
|
||||
20 'mutator_name_for'
|
||||
21 'new'
|
||||
22 'set'
|
||||
|
||||
As you can see, Object::Tiny adds 2 methods to your class, Class::Accessor
|
||||
adds 16 methods, plus one extra one for every accessor.
|
||||
|
||||
B<Object::Tiny doesn't have any of the caveats of Class::Accessor::Fast>
|
||||
|
||||
When you call B<use Object::Tiny qw{ foo bar baz }> it isn't treated as some
|
||||
sort of specification for the class, it's just a list of accessors you want
|
||||
made for you.
|
||||
|
||||
So if you want to customize C<foo> you don't need to get into contortions with
|
||||
"pure" base classes or calling alternate internal methods. Just make your own
|
||||
C<foo> method and remove C<foo> from the list passed to the C<use> call.
|
||||
|
||||
B<Object::Tiny is more back-compatible than Class::Accessor::Fast>
|
||||
|
||||
Class::Accessor::Fast has a minimum Perl dependency of 5.005002.
|
||||
|
||||
Object::Tiny has a minimum Perl dependency of 5.004.
|
||||
|
||||
B<Object::Tiny has no module dependencies whatsoever>
|
||||
|
||||
Object::Tiny does not load ANYTHING at all outside of its own single .pm file.
|
||||
|
||||
So Object::Tiny will never get confused in odd situations due to old or weird
|
||||
versions of other modules (Class::Accessor::Fast has a dependency on base.pm,
|
||||
which has some caveats of its own).
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs should be reported via the CPAN bug tracker at
|
||||
|
||||
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Object-Tiny>
|
||||
|
||||
For other issues, contact the author.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Adam Kennedy E<lt>adamk@cpan.orgE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Config::Tiny>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2007 - 2011 Adam Kennedy.
|
||||
|
||||
This program is free software; you can redistribute
|
||||
it and/or modify it under the same terms as Perl itself.
|
||||
|
||||
The full text of the license can be found in the
|
||||
LICENSE file included with this module.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user