Add Moose package
All checks were successful
release / release-plugins (push) Successful in 28s

This commit is contained in:
mschuepbach
2024-04-24 13:33:38 +02:00
parent 24101a5c1a
commit d95734d3d0
413 changed files with 47294 additions and 1 deletions

View File

@@ -0,0 +1,709 @@
# PODNAME: Moose::Manual::Attributes
# ABSTRACT: Object attributes with Moose
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Attributes - Object attributes with Moose
=head1 VERSION
version 2.2207
=head1 INTRODUCTION
Moose attributes have many properties, and attributes are probably the
single most powerful and flexible part of Moose. You can create a
powerful class simply by declaring attributes. In fact, it's possible
to have classes that consist solely of attribute declarations.
An attribute is a property that every member of a class has. For
example, we might say that "every C<Person> object has a first name and
last name". Attributes can be optional, so that we can say "some C<Person>
objects have a social security number (and some don't)".
At its simplest, an attribute can be thought of as a named value (as
in a hash) that can be read and set. However, attributes can also have
defaults, type constraints, delegation and much more.
In other languages, attributes are also referred to as slots or
properties.
=head1 ATTRIBUTE OPTIONS
Use the C<has> function to declare an attribute:
package Person;
use Moose;
has 'first_name' => ( is => 'rw' );
This says that all C<Person> objects have an optional read-write
"first_name" attribute.
=head2 Read-write vs. read-only
The options passed to C<has> define the properties of the attribute. There are
many options, but in the simplest form you just need to set C<is>, which can
be either C<ro> (read-only) or C<rw> (read-write). When an attribute is C<rw>,
you can change it by passing a value to its accessor. When an attribute is
C<ro>, you may only read the current value of the attribute through its
accessor. You can, however, set the attribute when creating the object by
passing it to the constructor.
In fact, you could even omit C<is>, but that gives you an attribute
that has no accessor. This can be useful with other attribute options,
such as C<handles>. However, if your attribute generates I<no>
accessors, Moose will issue a warning, because that usually means the
programmer forgot to say the attribute is read-only or read-write. If
you really mean to have no accessors, you can silence this warning by
setting C<is> to C<bare>.
=head2 Accessor methods
Each attribute has one or more accessor methods. An accessor lets you
read and write the value of that attribute for an object.
By default, the accessor method has the same name as the attribute. If
you declared your attribute as C<ro> then your accessor will be
read-only. If you declared it as C<rw>, you get a read-write
accessor. Simple.
Given our C<Person> example above, we now have a single C<first_name>
accessor that can read or write a C<Person> object's C<first_name>
attribute's value.
If you want, you can also explicitly specify the method names to be
used for reading and writing an attribute's value. This is
particularly handy when you'd like an attribute to be publicly
readable, but only privately settable. For example:
has 'weight' => (
is => 'ro',
writer => '_set_weight',
);
This might be useful if weight is calculated based on other methods.
For example, every time the C<eat> method is called, we might adjust
weight. This lets us hide the implementation details of weight
changes, but still provide the weight value to users of the class.
Some people might prefer to have distinct methods for reading and
writing. In I<Perl Best Practices>, Damian Conway recommends that
reader methods start with "get_" and writer methods start with "set_".
We can do exactly that by providing names for both the C<reader> and
C<writer> methods:
has 'weight' => (
is => 'rw',
reader => 'get_weight',
writer => 'set_weight',
);
If you're thinking that doing this over and over would be insanely
tedious, you're right! Fortunately, Moose provides a powerful
extension system that lets you override the default naming
conventions. See L<Moose::Manual::MooseX> for more details.
=head2 Predicate and clearer methods
Moose allows you to explicitly distinguish between a false or
undefined attribute value and an attribute which has not been set. If
you want to access this information, you must define clearer and
predicate methods for an attribute.
A predicate method tells you whether or not a given attribute is
currently set. Note that an attribute can be explicitly set to
C<undef> or some other false value, but the predicate will return
true.
The clearer method unsets the attribute. This is I<not> the
same as setting the value to C<undef>, but you can only distinguish
between them if you define a predicate method!
Here's some code to illustrate the relationship between an accessor,
predicate, and clearer method.
package Person;
use Moose;
has 'ssn' => (
is => 'rw',
clearer => 'clear_ssn',
predicate => 'has_ssn',
);
...
my $person = Person->new();
$person->has_ssn; # false
$person->ssn(undef);
$person->ssn; # returns undef
$person->has_ssn; # true
$person->clear_ssn;
$person->ssn; # returns undef
$person->has_ssn; # false
$person->ssn('123-45-6789');
$person->ssn; # returns '123-45-6789'
$person->has_ssn; # true
my $person2 = Person->new( ssn => '111-22-3333');
$person2->has_ssn; # true
By default, Moose does not make a predicate or clearer for you. You must
explicitly provide names for them, and then Moose will create the methods
for you.
=head2 Required or not?
By default, all attributes are optional, and do not need to be
provided at object construction time. If you want to make an attribute
required, simply set the C<required> option to true:
has 'name' => (
is => 'ro',
required => 1,
);
There are a couple caveats worth mentioning in regards to what
"required" actually means.
Basically, all it says is that this attribute (C<name>) must be provided to
the constructor or it must have either a default or a builder. It does not say
anything about its value, so it could be C<undef>.
If you define a clearer method on a required attribute, the clearer
I<will> work, so even a required attribute can be unset after object
construction.
This means that if you do make an attribute required, providing a
clearer doesn't make much sense. In some cases, it might be handy to
have a I<private> C<clearer> and C<predicate> for a required
attribute.
=head2 Default and builder methods
Attributes can have default values, and Moose provides two ways to
specify that default.
In the simplest form, you simply provide a non-reference scalar value
for the C<default> option:
has 'size' => (
is => 'ro',
default => 'medium',
predicate => 'has_size',
);
If the size attribute is not provided to the constructor, then it ends
up being set to C<medium>:
my $person = Person->new();
$person->size; # medium
$person->has_size; # true
You can also provide a subroutine reference for C<default>. This
reference will be called as a method on the object.
has 'size' => (
is => 'ro',
default =>
sub { ( 'small', 'medium', 'large' )[ int( rand 3 ) ] },
predicate => 'has_size',
);
This is a trivial example, but it illustrates the point that the subroutine
will be called for every new object created.
When you provide a C<default> subroutine reference, it is called as a
method on the object, with no additional parameters:
has 'size' => (
is => 'ro',
default => sub {
my $self = shift;
return $self->height > 200 ? 'large' : 'average';
},
);
When the C<default> is called during object construction, it may be
called before other attributes have been set. If your default is
dependent on other parts of the object's state, you can make the
attribute C<lazy>. Laziness is covered in the next section.
If you want to use a reference of any sort as the default value, you
must return it from a subroutine.
has 'mapping' => (
is => 'ro',
default => sub { {} },
);
This is necessary because otherwise Perl would instantiate the reference
exactly once, and it would be shared by all objects:
has 'mapping' => (
is => 'ro',
default => {}, # wrong!
);
Moose will throw an error if you pass a bare non-subroutine reference
as the default.
If Moose allowed this then the default mapping attribute could easily
end up shared across many objects. Instead, wrap it in a subroutine
reference as we saw above.
This is a bit awkward, but it's just the way Perl works.
As an alternative to using a subroutine reference, you can supply a C<builder>
method for your attribute:
has 'size' => (
is => 'ro',
builder => '_build_size',
predicate => 'has_size',
);
sub _build_size {
return ( 'small', 'medium', 'large' )[ int( rand 3 ) ];
}
This has several advantages. First, it moves a chunk of code to its own named
method, which improves readability and code organization. Second, because this
is a I<named> method, it can be subclassed or provided by a role.
We strongly recommend that you use a C<builder> instead of a
C<default> for anything beyond the most trivial default.
A C<builder>, just like a C<default>, is called as a method on the
object with no additional parameters.
=head3 Builders allow subclassing
Because the C<builder> is called I<by name>, it goes through Perl's
method resolution. This means that builder methods are both
inheritable and overridable.
If we subclass our C<Person> class, we can override C<_build_size>:
package Lilliputian;
use Moose;
extends 'Person';
sub _build_size { return 'small' }
=head3 Builders work well with roles
Because builders are called by name, they work well with roles. For
example, a role could provide an attribute but require that the
consuming class provide the C<builder>:
package HasSize;
use Moose::Role;
requires '_build_size';
has 'size' => (
is => 'ro',
lazy => 1,
builder => '_build_size',
);
package Lilliputian;
use Moose;
with 'HasSize';
sub _build_size { return 'small' }
Roles are covered in L<Moose::Manual::Roles>.
=head2 Laziness
Moose lets you defer attribute population by making an attribute
C<lazy>:
has 'size' => (
is => 'ro',
lazy => 1,
builder => '_build_size',
);
When C<lazy> is true, the default is not generated until the reader
method is called, rather than at object construction time. There are
several reasons you might choose to do this.
First, if the default value for this attribute depends on some other
attributes, then the attribute I<must> be C<lazy>. During object
construction, defaults are not generated in a predictable order, so
you cannot count on some other attribute being populated when
generating a default.
Second, there's often no reason to calculate a default before it's
needed. Making an attribute C<lazy> lets you defer the cost until the
attribute is needed. If the attribute is I<never> needed, you save
some CPU time.
We recommend that you make any attribute with a builder or non-trivial
default C<lazy> as a matter of course.
=head3 Lazy defaults and C<$_>
Please note that a lazy default or builder can be called anywhere, even inside
a C<map> or C<grep>. This means that if your default sub or builder changes
C<$_>, something weird could happen. You can prevent this by adding C<local
$_> inside your default or builder.
=head2 Constructor parameters (C<init_arg>)
By default, each attribute can be passed by name to the class's
constructor. On occasion, you may want to use a different name for
the constructor parameter. You may also want to make an attribute
unsettable via the constructor.
You can do either of these things with the C<init_arg> option:
has 'bigness' => (
is => 'ro',
init_arg => 'size',
);
Now we have an attribute named "bigness", but we pass C<size> to the
constructor.
Even more useful is the ability to disable setting an attribute via
the constructor. This is particularly handy for private attributes:
has '_genetic_code' => (
is => 'ro',
lazy => 1,
builder => '_build_genetic_code',
init_arg => undef,
);
By setting the C<init_arg> to C<undef>, we make it impossible to set
this attribute when creating a new object.
=head2 Weak references
Moose has built-in support for weak references. If you set the
C<weak_ref> option to a true value, then it will call
C<Scalar::Util::weaken> whenever the attribute is set:
has 'parent' => (
is => 'rw',
weak_ref => 1,
);
$node->parent($parent_node);
This is very useful when you're building objects that may contain
circular references.
When the object in a weak reference goes out of scope, the attribute's value
will become C<undef> "behind the scenes". This is done by the Perl interpreter
directly, so Moose does not see this change. This means that triggers don't
fire, coercions aren't applied, etc.
The attribute is not cleared, so a predicate method for that attribute will
still return true. Similarly, when the attribute is next accessed, a default
value will not be generated.
=head2 Triggers
A C<trigger> is a subroutine that is called whenever the attribute is
set:
has 'size' => (
is => 'rw',
trigger => \&_size_set,
);
sub _size_set {
my ( $self, $size, $old_size ) = @_;
my $msg = $self->name;
if ( @_ > 2 ) {
$msg .= " - old size was $old_size";
}
$msg .= " - size is now $size";
warn $msg;
}
The trigger is called I<after> an attribute's value is set. It is
called as a method on the object, and receives the new and old values as
its arguments. If the attribute had not previously been set at all,
then only the new value is passed. This lets you distinguish between
the case where the attribute had no value versus when the old value was C<undef>.
This differs from an C<after> method modifier in two ways. First, a
trigger is only called when the attribute is set, as opposed to
whenever the accessor method is called (for reading or
writing). Second, it is also called when an attribute's value is
passed to the constructor.
However, triggers are I<not> called when an attribute is populated
from a C<default> or C<builder>.
=head2 Attribute types
Attributes can be restricted to only accept certain types:
has 'first_name' => (
is => 'ro',
isa => 'Str',
);
This says that the C<first_name> attribute must be a string.
Moose also provides a shortcut for specifying that an attribute only
accepts objects that do a certain role:
has 'weapon' => (
is => 'rw',
does => 'MyApp::Weapon',
);
See the L<Moose::Manual::Types> documentation for a complete
discussion of Moose's type system.
=head2 Delegation
An attribute can define methods which simply delegate to its value:
has 'hair_color' => (
is => 'ro',
isa => 'Graphics::Color::RGB',
handles => { hair_color_hex => 'as_hex_string' },
);
This adds a new method, C<hair_color_hex>. When someone calls
C<hair_color_hex>, internally, the object just calls C<<
$self->hair_color->as_hex_string >>.
See L<Moose::Manual::Delegation> for documentation on how to set up
delegation methods.
=head2 Attribute traits and metaclasses
One of Moose's best features is that it can be extended in all sorts of ways
through the use of metaclass traits and custom metaclasses.
You can apply one or more traits to an attribute:
use MooseX::MetaDescription;
has 'size' => (
is => 'ro',
traits => ['MooseX::MetaDescription::Meta::Trait'],
description => {
html_widget => 'text_input',
serialize_as => 'element',
},
);
The advantage of traits is that you can mix more than one of them
together easily (in fact, a trait is just a role under the hood).
There are a number of MooseX modules on CPAN which provide useful
attribute metaclasses and traits. See L<Moose::Manual::MooseX> for
some examples. You can also write your own metaclasses and traits. See
the "Meta" and "Extending" recipes in L<Moose::Cookbook> for examples.
=head2 Native Delegations
Native delegations allow you to delegate to standard Perl data structures as
if they were objects.
For example, we can pretend that an array reference has methods like
C<push()>, C<shift()>, C<map()>, C<count()>, and more.
has 'options' => (
traits => ['Array'],
is => 'ro',
isa => 'ArrayRef[Str]',
default => sub { [] },
handles => {
all_options => 'elements',
add_option => 'push',
map_options => 'map',
option_count => 'count',
sorted_options => 'sort',
},
);
See L<Moose::Manual::Delegation> for more details.
=head1 ATTRIBUTE INHERITANCE
By default, a child inherits all of its parent class(es)' attributes
as-is. However, you can change most aspects of the inherited attribute in the
child class. You cannot change any of its associated method names (reader,
writer, predicate, etc).
To change some aspects of an attribute, you simply prepend a plus sign (C<+>)
to its name:
package LazyPerson;
use Moose;
extends 'Person';
has '+first_name' => (
lazy => 1,
default => 'Bill',
);
Now the C<first_name> attribute in C<LazyPerson> is lazy, and defaults
to C<'Bill'>.
We recommend that you exercise caution when changing the type (C<isa>)
of an inherited attribute.
=head2 Attribute Inheritance and Method Modifiers
When an inherited attribute is defined, that creates an entirely new set of
accessors for the attribute (reader, writer, predicate, etc.). This is
necessary because these may be what was changed when inheriting the attribute.
As a consequence, any method modifiers defined on the attribute's accessors in
an ancestor class will effectively be ignored, because the new accessors live
in the child class and do not see the modifiers from the parent class.
=head1 MULTIPLE ATTRIBUTE SHORTCUTS
If you have a number of attributes that differ only by name, you can declare
them all at once:
package Point;
use Moose;
has [ 'x', 'y' ] => ( is => 'ro', isa => 'Int' );
Also, because C<has> is just a function call, you can call it in a loop:
for my $name ( qw( x y ) ) {
my $builder = '_build_' . $name;
has $name => ( is => 'ro', isa => 'Int', builder => $builder );
}
=head1 MORE ON ATTRIBUTES
Moose attributes are a big topic, and this document glosses over a few
aspects. We recommend that you read the L<Moose::Manual::Delegation>
and L<Moose::Manual::Types> documents to get a more complete
understanding of attribute features.
=head1 A FEW MORE OPTIONS
Moose has lots of attribute options. The ones listed below are
superseded by some more modern features, but are covered for the sake
of completeness.
=head2 The C<documentation> option
You can provide a piece of documentation as a string for an attribute:
has 'first_name' => (
is => 'rw',
documentation => q{The person's first (personal) name},
);
Moose does absolutely nothing with this information other than store
it.
=head2 The C<auto_deref> option
If your attribute is an array reference or hash reference, the
C<auto_deref> option will make Moose dereference the value when it is
returned from the reader method I<in list context>:
my %map = $object->mapping;
This option only works if your attribute is explicitly typed as an
C<ArrayRef> or C<HashRef>. When the reader is called in I<scalar> context,
the reference itself is returned.
However, we recommend that you use L<Moose::Meta::Attribute::Native> traits
for these types of attributes, which gives you much more control over how
they are accessed and manipulated. See also
L<Moose::Manual::BestPractices#Use_Moose::Meta::Attribute::Native_traits_instead_of_auto_deref>.
=head2 Initializer
Moose provides an attribute option called C<initializer>. This is called when
the attribute's value is being set in the constructor, and lets you change the
value before it is set.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,292 @@
# PODNAME: Moose::Manual::BestPractices
# ABSTRACT: Get the most out of Moose
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::BestPractices - Get the most out of Moose
=head1 VERSION
version 2.2207
=head1 RECOMMENDATIONS
Moose has a lot of features, and there's definitely more than one way
to do it. However, we think that picking a subset of these features
and using them consistently makes everyone's life easier.
Of course, as with any list of "best practices", these are really just
opinions. Feel free to ignore us.
=head2 C<namespace::autoclean> and immutabilize
We recommend that you remove the Moose sugar and end your Moose class
definitions by making your class immutable.
package Person;
use Moose;
use namespace::autoclean;
# extends, roles, attributes, etc.
# methods
__PACKAGE__->meta->make_immutable;
1;
The C<use namespace::autoclean> bit is simply good code hygiene, as it removes
imported symbols from your class's namespace at the end of your package's
compile cycle, including Moose keywords. Once the class has been built, these
keywords are not needed. (This is preferred to placing C<no Moose> at the end
of your package).
The C<make_immutable> call allows Moose to speed up a lot of things, most
notably object construction. The trade-off is that you can no longer change
the class definition.
=head2 Never override C<new>
Overriding C<new> is a very bad practice. Instead, you should use a
C<BUILD> or C<BUILDARGS> methods to do the same thing. When you
override C<new>, Moose can no longer inline a constructor when your
class is immutabilized.
There are two good reasons to override C<new>. One, you are writing a
MooseX extension that provides its own L<Moose::Object> subclass
I<and> a subclass of L<Moose::Meta::Method::Constructor> to inline the
constructor. Two, you are subclassing a non-Moose parent.
If you know how to do that, you know when to ignore this best practice
;)
=head2 Always call the original/parent C<BUILDARGS>
If you C<override> the C<BUILDARGS> method in your class, make sure to play
nice and call C<super()> to handle cases you're not checking for explicitly.
The default C<BUILDARGS> method in L<Moose::Object> handles both a
list and hashref of named parameters correctly, and also checks for a
I<non-hashref> single argument.
=head2 Provide defaults whenever possible, otherwise use C<required>
When your class provides defaults, this makes constructing new objects
simpler. If you cannot provide a default, consider making the
attribute C<required>.
If you don't do either, an attribute can simply be left unset,
increasing the complexity of your object, because it has more possible
states that you or the user of your class must account for.
=head2 Use C<builder> instead of C<default> most of the time
Builders can be inherited, they have explicit names, and they're just
plain cleaner.
However, I<do> use a default when the default is a non-reference,
I<or> when the default is simply an empty reference of some sort.
Also, keep your builder methods private.
=head2 Be C<lazy>
Lazy is good, and often solves initialization ordering problems. It's also
good for deferring work that may never have to be done. Make your attributes
C<lazy> unless they're C<required> or have trivial defaults.
=head2 Consider keeping clearers and predicates private
Does everyone I<really> need to be able to clear an attribute?
Probably not. Don't expose this functionality outside your class
by default.
Predicates are less problematic, but there's no reason to make your
public API bigger than it has to be.
=head2 Avoid C<lazy_build>
As described above, you rarely actually need a clearer or a predicate.
C<lazy_build> adds both to your public API, which exposes you to use cases that
you must now test for. It's much better to avoid adding them until you really
need them - use explicit C<lazy> and C<builder> options instead.
=head2 Default to read-only, and consider keeping writers private
Making attributes mutable just means more complexity to account for in
your program. The alternative to mutable state is to encourage users
of your class to simply make new objects as needed.
If you I<must> make an attribute read-write, consider making the
writer a separate private method. Narrower APIs are easy to maintain,
and mutable state is trouble.
In order to declare such attributes, provide a private C<writer>
parameter:
has pizza => (
is => 'ro',
isa => 'Pizza',
writer => '_pizza',
);
=head2 Think twice before changing an attribute's type in a subclass
Down this path lies great confusion. If the attribute is an object
itself, at least make sure that it has the same interface as the type
of object in the parent class.
=head2 Don't use the C<initializer> feature
Don't know what we're talking about? That's fine.
=head2 Use L<Moose::Meta::Attribute::Native> traits instead of C<auto_deref>
The C<auto_deref> feature is a bit troublesome. Directly exposing a complex
attribute is ugly. Instead, consider using L<Moose::Meta::Attribute::Native>
traits to define an API that only exposes the necessary pieces of
functionality.
=head2 Always call C<inner> in the most specific subclass
When using C<augment> and C<inner>, we recommend that you call
C<inner> in the most specific subclass of your hierarchy. This makes
it possible to subclass further and extend the hierarchy without
changing the parents.
=head2 Namespace your types
Use some sort of namespacing convention for type names. We recommend something
like "MyApp::Type::Foo". We also recommend considering L<MooseX::Types>.
=head2 Do not coerce Moose built-ins directly
If you define a coercion for a Moose built-in like C<ArrayRef>, this
will affect every application in the Perl interpreter that uses this
type.
# very naughty!
coerce 'ArrayRef'
=> from Str
=> via { [ split /,/ ] };
Instead, create a subtype and coerce that:
subtype 'My::ArrayRef' => as 'ArrayRef';
coerce 'My::ArrayRef'
=> from 'Str'
=> via { [ split /,/ ] };
=head2 Do not coerce class names directly
Just as with Moose built-in types, a class type is global for the
entire interpreter. If you add a coercion for that class name, it can
have magical side effects elsewhere:
# also very naughty!
coerce 'HTTP::Headers'
=> from 'HashRef'
=> via { HTTP::Headers->new( %{$_} ) };
Instead, we can create an "empty" subtype for the coercion:
subtype 'My::HTTP::Headers' => as class_type('HTTP::Headers');
coerce 'My::HTTP::Headers'
=> from 'HashRef'
=> via { HTTP::Headers->new( %{$_} ) };
=head2 Use coercion instead of unions
Consider using a type coercion instead of a type union. This was
covered in L<Moose::Manual::Types>.
=head2 Define all your types in one module
Define all your types and coercions in one module. This was also
covered in L<Moose::Manual::Types>.
=head1 BENEFITS OF BEST PRACTICES
Following these practices has a number of benefits.
It helps ensure that your code will play nice with others, making it
more reusable and easier to extend.
Following an accepted set of idioms will make maintenance easier,
especially when someone else has to maintain your code. It will also
make it easier to get support from other Moose users, since your code
will be easier to digest quickly.
Some of these practices are designed to help Moose do the right thing,
especially when it comes to immutabilization. This means your code
will be faster when immutabilized.
Many of these practices also help get the most out of meta
programming. If you used an overridden C<new> to do type coercion by
hand, rather than defining a real coercion, there is no introspectable
metadata. This sort of thing is particularly problematic for MooseX
extensions which rely on introspection to do the right thing.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,218 @@
# PODNAME: Moose::Manual::Classes
# ABSTRACT: Making your classes use Moose (and subclassing)
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Classes - Making your classes use Moose (and subclassing)
=head1 VERSION
version 2.2207
=head1 USING MOOSE
Using Moose is very simple, you just C<use Moose>:
package Person;
use Moose;
That's it, you've made a class with Moose!
There's actually a lot going on here under the hood, so let's step
through it.
When you load L<Moose>, a bunch of sugar functions are exported into your
class, such as C<extends>, C<has>, C<with>, and more. These functions are what
you use to define your class. For example, you might define an attribute ...
package Person;
use Moose;
has 'ssn' => ( is => 'rw' );
Attributes are described in the L<Moose::Manual::Attributes>
documentation.
Loading Moose also enables the C<strict> and C<warnings> pragmas in your
class.
When you load Moose, your class will become a subclass of
L<Moose::Object>. The L<Moose::Object> class provides a default
constructor and destructor, as well as object construction helper
methods. You can read more about this in the
L<Moose::Manual::Construction> document.
As a convenience, Moose creates a new class type for your class. See
the L<Moose::Manual::Types> document to learn more about types.
It also creates a L<Moose::Meta::Class> object for your class. This
metaclass object is now available by calling a C<meta> method on your
class, for example C<< Person->meta >>.
The metaclass object provides an introspection API for your class. It
is also used by Moose itself under the hood to add attributes, define
parent classes, and so on. In fact, all of Moose's sugar does the real
work by calling methods on this metaclass object (and other meta API
objects).
=head1 SUBCLASSING
Moose provides a simple sugar function for declaring your parent
classes, C<extends>:
package User;
use Moose;
extends 'Person';
has 'username' => ( is => 'rw' );
Note that each call to C<extends> will I<reset> your parents. For
multiple inheritance you must provide all the parents at once,
C<extends 'Foo', 'Bar'>.
When you call C<extends> Moose will try to load any classes you pass.
You can use Moose to extend a non-Moose parent. However, when you do
this, you will inherit the parent class's constructor (assuming it is
also called C<new>). In that case, you will have to take care of
initializing attributes manually, either in the parent's constructor,
or in your subclass, and you will lose a lot of Moose magic.
See the L<MooseX::NonMoose> module on CPAN if you're interested in extending
non-Moose parent classes with Moose child classes.
=head1 CLEANING UP MOOSE DROPPINGS
Moose exports a number of functions into your class. It's a good idea to
remove these sugar functions from your class's namespace, so that C<<
Person->can('has') >> will no longer return true.
There are several ways to do this. We recommend using L<namespace::autoclean>,
a CPAN module. Not only will it remove Moose exports, it will also remove
any other exports.
package Person;
use namespace::autoclean;
use Moose;
If you absolutely can't use a CPAN module (but can use Moose?), you can write
C<no Moose> at the end of your class. This will remove any Moose exports in
your class.
package Person;
use Moose;
has 'ssn' => ( is => 'rw' );
no Moose;
=head1 MAKING IT FASTER
Moose has a feature called "immutabilization" that you can use to
greatly speed up your classes at runtime. However, using it incurs
a cost when your class is first being loaded. When you make your class
immutable you tell Moose that you will not be changing it in the
future. You will not be adding any more attributes, methods, roles, etc.
This allows Moose to generate code specific to your class. In
particular, it creates an "inline" constructor, making object
construction much faster.
To make your class immutable you simply call C<make_immutable> on your
class's metaclass object.
__PACKAGE__->meta->make_immutable;
=head2 Immutabilization and C<new()>
If you override C<new()> in your class, then the immutabilization code
will not be able to provide an optimized constructor for your
class. Instead, you should use a C<BUILD()> method, which will be
called from the inlined constructor.
Alternately, if you really need to provide a different C<new()>, you
can also provide your own immutabilization method. Doing so requires
extending the Moose metaclasses, and is well beyond the scope of this
manual.
=head1 INSTANTIATING CLASSES
When you're ready to use Moose classes in an application, reference them in
your code in the regular Perl OO way by including a C<use> directive
at the top of the file where the objects should be created.
use Person;
my $person = Person->new(
# attribute values at instantiation
# go here
ssn => '123456789',
);
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,439 @@
# PODNAME: Moose::Manual::Concepts
# ABSTRACT: Moose OO concepts
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Concepts - Moose OO concepts
=head1 VERSION
version 2.2207
=head1 MOOSE CONCEPTS (VS "OLD SCHOOL" Perl)
In the past, you may not have thought too much about the difference
between packages and classes, attributes and methods, constructors and
methods, etc. With Moose, these are all conceptually separate,
though under the hood they're implemented with plain old Perl.
Our meta-object protocol (aka MOP) provides well-defined introspection
features for each of those concepts, and Moose in turn provides
distinct sugar for each of them. Moose also introduces additional
concepts such as roles, method modifiers, and declarative delegation.
Knowing what these concepts mean in Moose-speak, and how they used to
be done in old school Perl 5 OO is a good way to start learning to use
Moose.
=head2 Class
When you say "use Moose" in a package, you are making your package a
class. At its simplest, a class will consist simply of attributes
and/or methods. It can also include roles, method modifiers, and more.
A class I<has> zero or more B<attributes>.
A class I<has> zero or more B<methods>.
A class I<has> zero or more superclasses (aka parent classes). A
class inherits from its superclass(es).
A class I<has> zero or more B<method modifiers>. These modifiers can
apply to its own methods or methods that are inherited from its
ancestors.
A class I<does> (and I<consumes>) zero or more B<roles>.
A class I<has> a B<constructor> and a B<destructor>. These are
provided for you "for free" by Moose.
The B<constructor> accepts named parameters corresponding to the
class's attributes and uses them to initialize an B<object instance>.
A class I<has> a B<metaclass>, which in turn has B<meta-attributes>,
B<meta-methods>, and B<meta-roles>. This metaclass I<describes> the
class.
A class is usually analogous to a category of nouns, like "People" or
"Users".
package Person;
use Moose;
# now it's a Moose class!
=head2 Attribute
An attribute is a property of the class that defines it. It I<always>
has a name, and it I<may have> a number of other properties.
These properties can include a read/write flag, a B<type>, accessor
method names, B<delegations>, a default value, and more.
Attributes I<are not> methods, but defining them causes various
accessor methods to be created. At a minimum, a normal attribute will
have a reader accessor method. Many attributes have other
methods, such as a writer method, a clearer method, or a predicate method
("has it been set?").
An attribute may also define B<delegations>, which will create
additional methods based on the delegation mapping.
By default, Moose stores attributes in the object instance, which is a
hashref, I<but this is invisible to the author of a Moose-based
class>! It is best to think of Moose attributes as "properties" of
the I<opaque> B<object instance>. These properties are accessed
through well-defined accessor methods.
An attribute is something that the class's members have. For example,
People have first and last names. Users have passwords and last login
datetimes.
has 'first_name' => (
is => 'rw',
isa => 'Str',
);
=head2 Method
A B<method> is very straightforward. Any subroutine you define in your
class is a method.
B<Methods> correspond to verbs, and are what your objects can do. For
example, a User can login.
sub login { ... }
=head2 Role
A role is something that a class I<does>. We also say that classes
I<consume> roles. For example, a Machine class might do the Breakable
role, and so could a Bone class. A role is used to define some concept
that cuts across multiple unrelated classes, like "breakability", or
"has a color".
A role I<has> zero or more B<attributes>.
A role I<has> zero or more B<methods>.
A role I<has> zero or more B<method modifiers>.
A role I<has> zero or more B<required methods>.
A required method is not implemented by the role. Required methods are a way
for the role to declare "to use this role you must implement this method".
A role I<has> zero or more B<excluded roles>.
An excluded role is a role that the role doing the excluding says it
cannot be combined with.
Roles are I<composed> into classes (or other roles). When a role is
composed into a class, its attributes and methods are "flattened" into
the class. Roles I<do not> show up in the inheritance hierarchy. When
a role is composed, its attributes and methods appear as if they were
defined I<in the consuming class>.
Role are somewhat like mixins or interfaces in other OO languages.
package Breakable;
use Moose::Role;
requires 'break';
has 'is_broken' => (
is => 'rw',
isa => 'Bool',
);
after 'break' => sub {
my $self = shift;
$self->is_broken(1);
};
=head2 Method modifiers
A B<method modifier> is a hook that is called when a named method is
called. For example, you could say "before calling C<login()>, call
this modifier first". Modifiers come in different flavors like
"before", "after", "around", and "augment", and you can apply more
than one modifier to a single method.
Method modifiers are often used as an alternative to overriding a
method in a parent class. They are also used in roles as a way of
modifying methods in the consuming class.
Under the hood, a method modifier is just a plain old Perl subroutine
that gets called before or after (or around, etc.) some named method.
before 'login' => sub {
my $self = shift;
my $pw = shift;
warn "Called login() with $pw\n";
};
=head2 Type
Moose also comes with a (miniature) type system. This allows you to define
types for attributes. Moose has a set of built-in types based on the types
Perl provides in its core, such as C<Str>, C<Num>, C<Bool>, C<HashRef>, etc.
In addition, every class name in your application can also be used as
a type name.
Finally, you can define your own types with their own constraints. For
example, you could define a C<PosInt> type, a subtype of C<Int> which only
allows positive numbers.
=head2 Delegation
Moose attributes provide declarative syntax for defining delegations. A
delegation is a method which in turn calls some method on an attribute to do
its real work.
=head2 Constructor
A constructor creates an B<object instance> for the class. In old
school Perl, this was usually done by defining a method called
C<new()> which in turn called C<bless> on a reference.
With Moose, this C<new()> method is created for you, and it simply
does the right thing. You should never need to define your own
constructor!
Sometimes you want to do something whenever an object is created. In
those cases, you can provide a C<BUILD()> method in your class. Moose
will call this for you after creating a new object.
=head2 Destructor
This is a special method called when an object instance goes out of
scope. You can specialize what your class does in this method if you
need to, but you usually don't.
With old school Perl 5, this is the C<DESTROY()> method, but with
Moose it is the C<DEMOLISH()> method.
=head2 Object instance
An object instance is a specific noun in the class's "category". For
example, one specific Person or User. An instance is created by the
class's B<constructor>.
An instance has values for its attributes. For example, a specific
person has a first and last name.
In old school Perl 5, this is often a blessed hash reference. With
Moose, you should never need to know what your object instance
actually is. (Okay, it's usually a blessed hashref with Moose, too.)
=head2 Moose vs old school summary
=over 4
=item * Class
A package with no introspection other than mucking about in the symbol
table.
With Moose, you get well-defined declaration and introspection.
=item * Attributes
Hand-written accessor methods, symbol table hackery, or a helper
module like C<Class::Accessor>.
With Moose, these are declaratively defined, and distinct from
methods.
=item * Method
These are pretty much the same in Moose as in old school Perl.
=item * Roles
C<Class::Trait> or C<Class::Role>, or maybe C<mixin.pm>.
With Moose, they're part of the core feature set, and are
introspectable like everything else.
=item * Method Modifiers
Could only be done through serious symbol table wizardry, and you
probably never saw this before (at least in Perl 5).
=item * Type
Hand-written parameter checking in your C<new()> method and accessors.
With Moose, you define types declaratively, and then use them by name
with your attributes.
=item * Delegation
C<Class::Delegation> or C<Class::Delegator>, but probably even more
hand-written code.
With Moose, this is also declarative.
=item * Constructor
A C<new()> method which calls C<bless> on a reference.
Comes for free when you define a class with Moose.
=item * Destructor
A C<DESTROY()> method.
With Moose, this is called C<DEMOLISH()>.
=item * Object Instance
A blessed reference, usually a hash reference.
With Moose, this is an opaque thing which has a bunch of attributes
and methods, as defined by its class.
=item * Immutabilization
Moose comes with a feature called "immutabilization". When you make
your class immutable, it means you're done adding methods, attributes,
roles, etc. This lets Moose optimize your class with a bunch of
extremely dirty in-place code generation tricks that speed up things
like object construction and so on.
=back
=head1 META WHAT?
A metaclass is a class that describes classes. With Moose, every class you
define gets a C<meta()> method. The C<meta()> method returns a
L<Moose::Meta::Class> object, which has an introspection API that can tell you
about the class it represents.
my $meta = User->meta();
for my $attribute ( $meta->get_all_attributes ) {
print $attribute->name(), "\n";
if ( $attribute->has_type_constraint ) {
print " type: ", $attribute->type_constraint->name, "\n";
}
}
for my $method ( $meta->get_all_methods ) {
print $method->name, "\n";
}
Almost every concept we defined earlier has a meta class, so we have
L<Moose::Meta::Class>, L<Moose::Meta::Attribute>,
L<Moose::Meta::Method>, L<Moose::Meta::Role>,
L<Moose::Meta::TypeConstraint>, L<Moose::Meta::Instance>, and so on.
=head1 BUT I NEED TO DO IT MY WAY!
One of the great things about Moose is that if you dig down and find
that it does something the "wrong way", you can change it by extending
a metaclass. For example, you can have arrayref based objects, you can
make your constructors strict (no unknown parameters allowed!), you can
define a naming scheme for attribute accessors, you can make a class a
Singleton, and much, much more.
Many of these extensions require surprisingly small amounts of code,
and once you've done it once, you'll never have to hand-code "your way
of doing things" again. Instead you'll just load your favorite
extensions.
package MyWay::User;
use Moose;
use MooseX::StrictConstructor;
use MooseX::MyWay;
has ...;
=head1 WHAT NEXT?
So you're sold on Moose. Time to learn how to really use it.
If you want to see how Moose would translate directly into old school
Perl 5 OO code, check out L<Moose::Manual::Unsweetened>. This might be
helpful for quickly wrapping your brain around some aspects of "the
Moose way".
Or you can skip that and jump straight to L<Moose::Manual::Classes>
and the rest of the L<Moose::Manual>.
After that we recommend that you start with the L<Moose::Cookbook>. If
you work your way through all the recipes under the basics section,
you should have a pretty good sense of how Moose works, and all of its
basic OO features.
After that, check out the Role recipes. If you're really curious, go
on and read the Meta and Extending recipes, but those are mostly there
for people who want to be Moose wizards and extend Moose itself.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,228 @@
# PODNAME: Moose::Manual::Construction
# ABSTRACT: Object construction (and destruction) with Moose
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Construction - Object construction (and destruction) with Moose
=head1 VERSION
version 2.2207
=head1 WHERE'S THE CONSTRUCTOR?
B<Do not define a C<new()> method for your classes!>
When you C<use Moose> in your class, your class becomes a subclass of
L<Moose::Object>. The L<Moose::Object> provides a C<new()> method for your
class. If you follow our recommendations in L<Moose::Manual::BestPractices>
and make your class immutable, then you actually get a class-specific C<new()>
method "inlined" in your class.
=head1 OBJECT CONSTRUCTION AND ATTRIBUTES
The Moose-provided constructor accepts a hash or hash reference of
named parameters matching your attributes (actually, matching their
C<init_arg>s). This is just another way in which Moose keeps you from
worrying I<how> classes are implemented. Simply define a class and
you're ready to start creating objects!
=head1 OBJECT CONSTRUCTION HOOKS
Moose lets you hook into object construction. You can validate an
object's state, do logging, customize construction from parameters which
do not match your attributes, or maybe allow non-hash(ref) constructor
arguments. You can do this by creating C<BUILD> and/or C<BUILDARGS>
methods.
If these methods exist in your class, Moose will arrange for them to
be called as part of the object construction process.
=head2 BUILDARGS
The C<BUILDARGS> method is called as a class method I<before> an
object is created. It will receive all of the arguments that were
passed to C<new()> I<as-is>, and is expected to return a hash
reference. This hash reference will be used to construct the object,
so it should contain keys matching your attributes' names (well,
C<init_arg>s).
One common use for C<BUILDARGS> is to accommodate a non-hash(ref)
calling style. For example, we might want to allow our Person class to
be called with a single argument of a social security number, C<<
Person->new($ssn) >>.
Without a C<BUILDARGS> method, Moose will complain, because it expects
a hash or hash reference. We can use the C<BUILDARGS> method to
accommodate this calling style:
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
if ( @_ == 1 && !ref $_[0] ) {
return $class->$orig( ssn => $_[0] );
}
else {
return $class->$orig(@_);
}
};
Note the call to C<< $class->$orig >>. This will call the default C<BUILDARGS>
in L<Moose::Object>. This method takes care of distinguishing between a hash
reference and a plain hash for you.
=head2 BUILD
The C<BUILD> method is called I<after> an object is created. There are
several reasons to use a C<BUILD> method. One of the most common is to
check that the object state is valid. While we can validate individual
attributes through the use of types, we can't validate the state of a
whole object that way.
sub BUILD {
my $self = shift;
if ( $self->country_of_residence eq 'USA' ) {
die 'All US residents must have an SSN'
unless $self->has_ssn;
}
}
Another use of a C<BUILD> method could be for logging or tracking
object creation.
sub BUILD {
my $self = shift;
debug( 'Made a new person - SSN = ', $self->ssn, );
}
The C<BUILD> method is called with the hash reference of the parameters passed
to the constructor (after munging by C<BUILDARGS>). This gives you a chance to
do something with parameters that do not represent object attributes.
sub BUILD {
my $self = shift;
my $args = shift;
$self->add_friend(
My::User->new(
user_id => $args->{user_id},
)
);
}
=head3 BUILD and parent classes
The interaction between multiple C<BUILD> methods in an inheritance hierarchy
is different from normal Perl methods. B<You should never call C<<
$self->SUPER::BUILD >>>, nor should you ever apply a method modifier to
C<BUILD>. Roles are an exception to this rule, though: it's completely
acceptable to apply a method modifier to C<BUILD> in a role; you can
even provide an empty C<BUILD> subroutine in a role so the role is applicable
even to classes without their own C<BUILD>.
Moose arranges to have all of the C<BUILD> methods in a hierarchy
called when an object is constructed, I<from parents to
children>. This might be surprising at first, because it reverses the
normal order of method inheritance.
The theory behind this is that C<BUILD> methods can only be used for
increasing specialization of a class's constraints, so it makes sense
to call the least specific C<BUILD> method first. Also, this is how
Perl 6 does it.
=head1 OBJECT DESTRUCTION
Moose provides a hook for object destruction with the C<DEMOLISH>
method. As with C<BUILD>, you should never explicitly call C<<
$self->SUPER::DEMOLISH >>. Moose will arrange for all of the
C<DEMOLISH> methods in your hierarchy to be called, from most to least
specific.
Each C<DEMOLISH> method is called with a single argument. This is a boolean
value indicating whether or not this method was called as part of the global
destruction process (when the Perl interpreter exits).
In most cases, Perl's built-in garbage collection is sufficient, and
you won't need to provide a C<DEMOLISH> method.
=head2 Error Handling During Destruction
The interaction of object destruction and Perl's global C<$@> and C<$?>
variables can be very confusing.
Moose always localizes C<$?> when an object is being destroyed. This means
that if you explicitly call C<exit>, that exit code will be preserved even if
an object's destructor makes a system call.
Moose also preserves C<$@> against any C<eval> calls that may happen during
object destruction. However, if an object's C<DEMOLISH> method actually dies,
Moose explicitly rethrows that error.
If you do not like this behavior, you will have to provide your own C<DESTROY>
method and use that instead of the one provided by L<Moose::Object>. You can
do this to preserve C<$@> I<and> capture any errors from object destruction by
creating an error stack.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,545 @@
# PODNAME: Moose::Manual::Contributing
# ABSTRACT: How to get involved in Moose
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Contributing - How to get involved in Moose
=head1 VERSION
version 2.2207
=for comment CONTRIBUTING.pod is generated from lib/Moose/Manual/Contributing.pod
=head1 GETTING INVOLVED
Moose is an open project, and we are always willing to accept bug fixes,
more tests, and documentation patches. Commit bits are given out freely and
it's easy to get started!
=head2 Get the Code
If you just want to get your feet wet and check out the code, you can do so
from the comfort of your web browser by going to the official repository on
GitHub: L<https://github.com/moose/Moose>.
However, if you know how to use git and would rather have a local copy
(because, why wouldn't you?!), then you can clone it:
git clone git@github.com:moose/Moose.git
If, at some point, you think you'd like to contribute a patch, please see
L</Getting Started>.
I<B<NOTE:> Your contribution is very important to us. If, for some reason,
you would prefer not to use Git/GitHub, come talk to us at #moose on
irc.perl.org and we can work something out.>
=head2 People
As Moose has matured, some structure has emerged in the process.
=over
=item Cabal - people who can release moose
These people are the ones who have co-maint on Moose itself and can create a
release. They're listed under L<Moose/CABAL> in the Moose documentation. They
are responsible for reviewing branches, and are the only people who are
allowed to push to stable branches.
Cabal members are listed in L<Moose> and can often be found on irc in the
L<irc://irc.perl.org/#moose-dev> channel.
=item Contributors - people creating a topic or branch
You!
=back
=head2 New Features
Moose already has a fairly large feature set, and we are currently
B<not> looking to add any major new features to it. If you have an
idea for a new feature in Moose, you are encouraged to create a
MooseX module first.
At this stage, no new features will even be considered for addition
into the core without first being vetted as a MooseX module, unless
it is absolutely 100% impossible to implement the feature outside the
core.
If you think it is 100% impossible, please come discuss it with us on IRC or
via e-mail. Your feature may need a small hook in the core, or a
refactoring of some core modules, and we are definitely open to that.
Moose was built from the ground up with the idea of being highly extensible,
and quite often the feature requests we see can be implemented through small
extensions. Try it, it's much easier than you might think.
=head2 Branch Layout
The repository is divided into several branches to make maintenance easier for
everyone involved. The branches below are ordered by level of stability.
=over
=item stable/*
The branch from which releases are cut. When making a new major release, the
release manager makes a new C<stable/X.YY> branch at the current position of
C<master>. The version used in the stable branch should not include the last
two digits of the version number.
For minor releases, patches will be committed to C<master>, and
backported (cherry-picked) to the appropriate stable branch as needed. A
stable branch is only updated by someone from the Cabal during a release.
=item master
The main development branch. All new code should be written against this
branch. This branch contains code that has been reviewed, and will be included
in the next major release. Commits which are judged to not break backwards
compatibility may be backported into C<stable> to be included in the next minor
release.
=item topic/*
Small personal branches that are still in progress. They can be freely rebased.
They contain targeted features that may span a handful of commits. Any change
or bugfix should be created in a topic branch.
=item rfc/*
Topic branches that are completed and waiting on review. A Cabal member will
look over branches in this namespace, and either merge them to C<master> if
they are acceptable, or move them back to a different namespace otherwise.
This namespace is being phased out now that we are using GitHub's pull
requests in our L</Development Workflow>.
=item attic/*
Branches which have been reviewed, and rejected. They remain in the repository
in case we later change our mind, or in case parts of them are still useful.
=item abandoned/*
Topic branches which have had no activity for a long period of time will be
moved here, to keep the main areas clean.
=back
Larger, longer term branches can also be created in the root namespace (i.e.
at the same level as master and stable). This may be appropriate if multiple
people are intending to work on the branch. These branches should not be
rebased without checking with other developers first.
=head1 WORKFLOWS
=head2 Getting Started
So, you've cloned the main Moose repository to your local machine (see
L</Get the Code>) and you're ready to do some hacking. We couldn't be
happier to welcome you to our community!
Of course, to ensure that your first experience is as productive and
satisfying as possible, you should probably take some time to read over this
entire POD document. Doing so will give you a full understanding of how Moose
developers and maintainers work together and what they expect from one
another. Done? Great!
Next, assuming you have a GitHub account, go to
L<http://github.com/moose/Moose> and B<fork the repository> (see
L<https://help.github.com/articles/fork-a-repo>). This will put an exact
replica of the Moose repository into your GitHub account, which will serve as
a place to publish your patches for the Moose maintainers to review and
incorporate.
Once your fork has been created, switch to your local working repository directory
and update your C<origin> remote's push URL. This allows you to use a single
remote (C<origin>) to both pull in the latest code from GitHub and also push
your work to your own fork:
# Replace YOUR_USERNAME below with your GitHub username
git remote set-url --push origin git@github.com:YOUR_USERNAME/moose.git
You can verify your work:
$ git remote -v
origin git@github.com:moose/Moose.git (fetch)
origin git@github.com:YOUR_USERNAME/moose.git (push)
Now, you're ready for action! From now on, you just follow the L</Development
Workflow> to publish your work and B<submit pull requests> to the Moose Cabal.
=head2 Development Workflow
The general gist of the B<STANDARD WORKFLOW> is:
=over 4
=item 1. Update your local repository with the latest commits from the official repository
=item 2. Create a new topic branch, based on the master branch
=item 3. Hack away
=item 4. Commit and push the topic branch to your forked repository
=item 5. Submit a pull request through GitHub for that branch
=back
What follows is a more detailed rundown of that workflow. Please make sure to
review and follow the steps in the previous section, L</Getting Started>, if
you have not done so already.
=head3 Update Your Repository
Update your local copy of the master branch from the remote:
git checkout master
git pull --rebase
=head3 Create Your Topic Branch
Now, create a new topic branch based on your master branch. It's useful to
use concise, descriptive branch names such as: pod-syntax-contrib,
feat-autodelegation, patch-23-role-comp, etc. However, we'll just call ours
C<my-feature> for demonstration purposes:
git checkout -b topic/my-feature
=head3 Hack. Commit. Repeat.
While you're hacking, the most important thing to remember is that your topic
branch is yours to do with as you like. Nothing you do there will affect
anyone else at this point. Commit as often as little or as often as you need
to and don't let perfection get in the way of progress. However, don't try to
do too much as the easiest changes to integrate are small and focused.
If it's been a while since you created your topic branch, it's often a good
idea to periodically rebase your branch off of the upstream master to reduce
your work later on:
git fetch # or, git remote update
git rebase origin/master # or, git pull --rebase origin master
You should also feel free to publish (using C<push --force> if necessary) your
branch to your GitHub fork if you simply need feedback from others. (Note:
actual collaboration takes a bit more finesse and a lot less C<--force>
however).
=head3 Clean Up Your Branch
Finally, when your development is done, it's time to prepare your branch for
review. Even the smallest branches can often use a little bit of tidying up
before they are unleashed on a reviewer. Clarifying/cleaning up commit
messages, reordering commits, splitting large commits or those which contain
different types of changes, squashing related or straggler commits are all
B<highly> worthwhile activities to undertake on your topic branch.
B<Remember:> Your topic branch is yours. Don't worry about rewriting its
history or breaking fast-forward. Some useful commands are listed below but
please make sure that you understand what they do as they can rewrite history:
- git commit --amend
- git rebase --interactive
- git cherry-pick
Ultimately, your goal in cleaning up your branch is to craft a set of commits
whose content and messages are as focused and understandable as possible.
Doing so will greatly increase the chances of a speedy review and acceptance
into the mainline development.
=head3 Rebase on the Latest
Before your final push and issuing a pull request, you need to ensure that
your changes can be easily merged into the master branch of the upstream
repository. This is done by once again rebasing your branch on the latest
C<origin/master>.
git fetch # or, git remote update
git rebase origin/master # or, git pull --rebase origin master
=head3 Publish and Pull Request
Now it's time to make your final push of the branch to your fork. The
C<--force> flag is only necessary if you've pushed before and subsequently
rewriting your history:
git push --force
After your branch is published, you can issue a pull request to the Moose
Cabal. See <https://help.github.com/articles/using-pull-requests> for details.
Congratulations! You're now a contributor!
=head2 Approval Workflow
Moose is an open project but it is also an increasingly important one. Many
modules depend on Moose being stable. Therefore, we have a basic set of
criteria for reviewing and merging branches. What follows is a set of rough
guidelines that ensures all new code is properly vetted before it is merged to
the master branch.
It should be noted that if you want your specific branch to be approved, it is
B<your> responsibility to follow this process and advocate for your branch.
=over 4
=item Small bug fixes, doc patches and additional passing tests.
These items don't really require approval beyond one of the core contributors
just doing a simple review. For especially simple patches (doc patches
especially), committing directly to master is fine.
=item Larger bug fixes, doc additions and TODO or failing tests.
Larger bug fixes should be reviewed by at least one cabal member and should be
tested using the F<xt/author/test-my-dependents.t> test.
New documentation is always welcome, but should also be reviewed by a cabal
member for accuracy.
TODO tests are basically feature requests, see our L</New Features> section
for more information on that. If your feature needs core support, create a
C<topic/> branch using the L</Development Workflow> and start hacking away.
Failing tests are basically bug reports. You should find a core contributor
and/or cabal member to see if it is a real bug, then submit the bug and your
test to the RT queue. Source control is not a bug reporting tool.
=item New user-facing features.
Anything that creates a new user-visible feature needs to be approved by
B<more than one> cabal member.
Make sure you have reviewed L</New Features> to be sure that you are following
the guidelines. Do not be surprised if a new feature is rejected for the core.
=item New internals features.
New features for Moose internals are less restrictive than user facing
features, but still require approval by B<at least one> cabal member.
Ideally you will have run the F<xt/author/test-my-dependents.t> script to be sure you
are not breaking any MooseX module or causing any other unforeseen havoc. If
you do this (rather than make us do it), it will only help to hasten your
branch's approval.
=item Backwards incompatible changes.
Anything that breaks backwards compatibility must be discussed by the
cabal. Backwards incompatible changes should not be merged to master if there
are strong objections from any cabal members.
We have a policy for what we see as sane L</BACKWARDS COMPATIBILITY> for
Moose. If your changes break back-compat, you must be ready to discuss and
defend your change.
=back
=head2 Release Workflow
# major releases (including trial releases)
git checkout master
# minor releases
git checkout stable/X.YY
# do final changelogging, etc
git commit
dzil release # or dzil release --trial for trial releases
=head3 Release How-To
Moose uses L<Dist::Zilla> to manage releases. Although the git repository comes
with a C<Makefile.PL>, it is a very basic one just to allow the basic
C<perl Makefile.PL && make && make test> cycle to work. In particular, it
doesn't include any release metadata, such as dependencies. In order to get
started with Dist::Zilla, first install it: C<cpanm Dist::Zilla>, and then
install the plugins necessary for reading the C<dist.ini>:
C<dzil authordeps | cpanm>.
Moose releases fall into two categories, each with their own level of release
preparation. A minor release is one which does not include any API changes,
deprecations, and so on. In that case, it is sufficient to simply test the
release candidate against a few different Perls. Testing should be done against
at least two recent major versions of Perl (5.8.8 and 5.10.1, for example). If
you have more versions available, you are encouraged to test them all. However,
we do not put a lot of effort into supporting older 5.8.x releases.
For major releases which include an API change or deprecation, you should run
the F<xt/author/test-my-dependents.t> test. This tests a long list of MooseX
and other Moose-using modules from CPAN. In order to run this script, you must
arrange to have the new version of Moose in Perl's include path. You can use
C<prove -b> and C<prove -I>, install the module, or fiddle with the C<PERL5LIB>
environment variable, whatever makes you happy.
This test downloads each module from CPAN, runs its tests, and logs failures
and warnings to a set of files named F<test-mydeps-$$-*.log>. If there are
failures or warnings, please work with the authors of the modules in question
to fix them. If the module author simply isn't available or does not want to
fix the bug, it is okay to make a release.
Regardless of whether or not a new module is available, any breakages should
be noted in the conflicts list in the distribution's F<dist.ini>.
=head2 Emergency Bug Workflow (for immediate release)
The stable branch exists for easily making bug fix releases.
git remote update
git checkout -b topic/my-emergency-fix origin/master
# hack
git commit
Then a cabal member merges into C<master>, and backports the change into
C<stable/X.YY>:
git checkout master
git merge topic/my-emergency-fix
git push
git checkout stable/X.YY
git cherry-pick -x master
git push
# release
=head2 Project Workflow
For longer lasting branches, we use a subversion style branch layout, where
master is routinely merged into the branch. Rebasing is allowed as long as all
the branch contributors are using C<git pull --rebase> properly.
C<commit --amend>, C<rebase --interactive>, etc. are not allowed, and should
only be done in topic branches. Committing to master is still done with the
same review process as a topic branch, and the branch must merge as a fast
forward.
This is pretty much the way we're doing branches for large-ish things right
now.
Obviously there is no technical limitation on the number of branches. You can
freely create topic branches off of project branches, or sub projects inside
larger projects freely. Such branches should incorporate the name of the branch
they were made off so that people don't accidentally assume they should be
merged into master:
git checkout -b my-project--topic/foo my-project
(unfortunately Git will not allow C<my-project/foo> as a branch name if
C<my-project> is a valid ref).
=head1 BRANCH ARCHIVAL
Merged branches should be deleted.
Failed branches may be kept, but should be moved to C<attic/> to differentiate
them from in-progress topic branches.
Branches that have not been worked on for a long time will be moved to
C<abandoned/> periodically, but feel free to move the branch back to C<topic/>
if you want to start working on it again.
=head1 TESTS, TESTS, TESTS
If you write I<any> code for Moose, you B<must> add tests for that code. If you
do not write tests then we cannot guarantee your change will not be removed or
altered at a later date, as there is nothing to confirm this is desired
behavior.
If your code change/addition is deep within the bowels of Moose and your test
exercises this feature in a non-obvious way, please add some comments either
near the code in question or in the test so that others know.
We also greatly appreciate documentation to go with your changes, and an entry
in the Changes file. Make sure to give yourself credit! Major changes or new
user-facing features should also be documented in L<Moose::Manual::Delta>.
=head1 DOCS, DOCS, DOCS
Any user-facing changes must be accompanied by documentation. If you're not
comfortable writing docs yourself, you might be able to convince another Moose
dev to help you.
Our goal is to make sure that all features are documented. Undocumented
features are not considered part of the API when it comes to determining
whether a change is backwards compatible.
=head1 BACKWARDS COMPATIBILITY
Change is inevitable, and Moose is not immune to this. We do our best
to maintain backwards compatibility, but we do not want the code base
to become overburdened by this. This is not to say that we will be
frivolous with our changes, quite the opposite, just that we are not
afraid of change and will do our best to keep it as painless as
possible for the end user.
Our policy for handling backwards compatibility is documented in more detail in
L<Moose::Manual::Support>.
All backwards incompatible changes B<must> be documented in
L<Moose::Manual::Delta>. Make sure to document any useful tips or workarounds
for the change in that document.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,313 @@
# PODNAME: Moose::Manual::Delegation
# ABSTRACT: Attribute delegation
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Delegation - Attribute delegation
=head1 VERSION
version 2.2207
=head1 WHAT IS DELEGATION?
Delegation is a feature that lets you create "proxy" methods that do nothing
more than call some other method on an attribute. This lets you simplify a
complex set of "has-a" relationships and present a single unified API from one
class.
With delegation, consumers of a class don't need to know about all the
objects it contains, reducing the amount of API they need to learn.
Delegations are defined as a mapping between one or more methods
provided by the "real" class (the delegatee), and a set of
corresponding methods in the delegating class. The delegating class
can re-use the method names provided by the delegatee or provide its
own names.
Delegation is also a great way to wrap an existing class, especially a
non-Moose class or one that is somehow hard (or impossible) to
subclass.
=head1 DEFINING A MAPPING
Moose offers a number of options for defining a delegation's mapping,
ranging from simple to complex.
The simplest form is to simply specify a list of methods:
package Website;
use Moose;
has 'uri' => (
is => 'ro',
isa => 'URI',
handles => [qw( host path )],
);
Using an arrayref tells Moose to create methods in your class that match the
method names in the delegated class.
With this definition, we can call C<< $website->host >> and it "just
works". Under the hood, Moose will call C<< $website->uri->host >> for
you. Note that C<$website> is I<not> automatically passed to the C<host>
method; the invocant is C<< $website->uri >>.
We can also define a mapping as a hash reference. This allows you to
rename methods as part of the mapping:
package Website;
use Moose;
has 'uri' => (
is => 'ro',
isa => 'URI',
handles => {
hostname => 'host',
path => 'path',
},
);
Using a hash tells Moose to create method names (specified on the left) which
invoke the delegated class methods (specified on the right).
In this example, we've created a C<< $website->hostname >> method,
rather than simply using C<URI.pm>'s name, C<host> in the Website
class.
These two mapping forms are the ones you will use most often. The
remaining methods are a bit more complex.
has 'uri' => (
is => 'ro',
isa => 'URI',
handles => qr/^(?:host|path|query.*)/,
);
This is similar to the array version, except it uses the regex to
match against all the methods provided by the delegatee. In order for
this to work, you must provide an C<isa> parameter for the attribute,
and it must be a class. Moose uses this to introspect the delegatee
class and determine what methods it provides.
You can use a role name as the value of C<handles>:
has 'uri' => (
is => 'ro',
isa => 'URI',
handles => 'HasURI',
);
Moose will introspect the role to determine what methods it provides
and create a name-for-name mapping for each of those methods.
Finally, you can provide a sub reference to I<generate> a mapping that behaves
like the hash example above. You probably won't need this version often (if
ever). See the L<Moose> docs for more details on exactly how this works.
=head1 NATIVE DELEGATION
Native delegations allow you to delegate to standard Perl data structures as
if they were objects.
has 'queue' => (
traits => ['Array'],
isa => 'ArrayRef[Item]',
default => sub { [ ] },
handles => {
add_item => 'push',
next_item => 'shift',
},
)
The C<Array> trait in the C<traits> parameter tells Moose that you would like
to use the set of Array helpers. Moose will then create C<add_item> and
C<next_item> methods that "just work". Behind the scenes C<add_item> is
something like
sub add_item {
my ($self, @items) = @_;
for my $item (@items) {
$Item_TC->validate($item);
}
push @{ $self->queue }, @items;
}
For example, you might use Array helpers to add C<add_task> and
C<add_appointment> methods to a Calendar class:
has 'tasks' => (
traits => ['Array'],
isa => 'ArrayRef[Task]',
default => sub { [ ] },
handles => {
add_task => 'push',
next_task => 'shift',
},
);
has 'appointments' => (
traits => ['Array'],
isa => 'ArrayRef[Appointment]',
default => sub { [ ] },
handles => {
add_appointment => 'push',
next_appointment => 'shift',
},
);
Which you would call as:
$calendar->add_task( $task_obj );
$calendar->add_appointment( $appointment_obj );
As mentioned above, each trait provides a number of methods which are
summarized below. For more information about each of these provided methods
see the documentation for that specific trait.
Moose includes the following traits for native delegation.
=over 4
=item * L<Array|Moose::Meta::Attribute::Native::Trait::Array>
The following methods are provided by the native Array trait:
count, is_empty, elements, get, pop, push, shift, unshift, splice, first,
first_index, grep, map, reduce, sort, sort_in_place, shuffle, uniq, join, set,
delete, insert, clear, accessor, natatime, shallow_clone
=item * L<Bool|Moose::Meta::Attribute::Native::Trait::Bool>
The following methods are provided by the native Bool trait:
set, unset, toggle, not
=item * L<Code|Moose::Meta::Attribute::Native::Trait::Code>
The following methods are provided by the native Code trait:
execute, execute_method
=item * L<Counter|Moose::Meta::Attribute::Native::Trait::Counter>
The following methods are provided by the native Counter trait:
set, inc, dec, reset
=item * L<Hash|Moose::Meta::Attribute::Native::Trait::Hash>
The following methods are provided by the native Hash trait:
get, set, delete, keys, exists, defined, values, kv, elements, clear, count,
is_empty, accessor, shallow_clone
=item * L<Number|Moose::Meta::Attribute::Native::Trait::Number>
The following methods are provided by the native Number trait:
add, sub, mul, div, mod, abs
=item * L<String|Moose::Meta::Attribute::Native::Trait::String>
The following methods are provided by the native String trait:
inc, append, prepend, replace, match, chop, chomp, clear, length, substr
=back
=head1 CURRYING
Currying allows you to create a method with some pre-set parameters. You can
create a curried delegation method:
package Spider;
use Moose;
has request => (
is => 'ro'
isa => 'HTTP::Request',
handles => {
set_user_agent => [ header => 'UserAgent' ],
},
)
With this definition, calling C<< $spider->set_user_agent('MyClient') >> will
call C<< $spider->request->header('UserAgent', 'MyClient') >> behind the
scenes.
Note that with currying, the currying always starts with the first parameter to
a method (C<$_[0]>). Any arguments you pass to the delegation come after the
curried arguments.
=head1 MISSING ATTRIBUTES
It is perfectly valid to delegate methods to an attribute which is not
required or can be undefined. When a delegated method is called, Moose
will throw a runtime error if the attribute does not contain an
object.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

1275
CPAN/Moose/Manual/Delta.pod Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,239 @@
# PODNAME: Moose::Manual::Exceptions
# ABSTRACT: Moose's exceptions
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Exceptions - Moose's exceptions
=head1 VERSION
version 2.2207
=head1 EXCEPTIONS IN MOOSE
Moose will throw an exception for all error conditions. This applies both to
code in the Moose core I<as well> as to all code generated when a class is
made immutable. All exceptions are subclasses of the C<Moose::Exception>
class.
Each type of error has its own unique subclass, and many subclasses have
additional attributes to provide more information about the error's context,
such as what classes or roles were involved.
=head1 EXCEPTION STRINGIFICATION
By default, Moose exceptions remove Moose internals from the stack trace. If
you set the C<MOOSE_FULL_EXCEPTION> environment variable to a true value, then
the Moose internals will be included in the trace.
=head1 HANDLING MOOSE EXCEPTIONS
Because Moose's exceptions use the standard C<die> mechanism, you are free to
catch and handle errors however you like. You could use an C<eval> block to
catch Moose exceptions. However, the Moose team strongly recommends using
L<Try::Tiny> instead. Please refer to L<Try::Tiny>'s documentation for a
discussion of how C<eval> is dangerous.
The following example demonstrates how to catch and inspect a
L<Moose::Exception>. For the sake of simplicity, we will cause a very simple
error. The C<extends> keywords expects a list of superclass names. If we pass
no superclass names, Moose will throw an instance of
L<Moose::Exception::ExtendsMissingArgs>.
=head2 Catching with Try::Tiny
use warnings;
use strict;
use Try::Tiny;
try {
package Example::Exception;
use Moose;
extends; # <-- error!
}
catch {
# $_ contains the instance of the exception thrown by the above try
# block, but $_ may get clobbered, so we should copy its value to
# another variable.
my $e = $_;
# Exception objects are not ubiquitous in Perl, so we must check
# whether $e is blessed. We also need to ensure that $e is actually
# the kind of exception we were expecting.
if ( blessed $e
&& $e->isa('Moose::Exception::ExtendsMissingArgs') ) {
my $class_name = $e->class_name;
warn "You forgot to specify a superclass for $class_name, silly!";
}
# It's either another type of an object or not an object at all.
else {
warn "$e\n";
}
};
=head2 Example of catching ValidationFailedForTypeConstraint
use warnings;
use strict;
use Try::Tiny;
{
package Person;
use Moose;
use Moose::Util::TypeConstraints;
subtype 'NameStr',
as 'Str',
where { $_ =~ /^[a-zA-Z]+$/; };
has age => (
is => 'ro',
isa => 'Int',
required => 1
);
has name => (
is => 'ro',
isa => 'NameStr',
required => 1
);
}
my $person;
while ( !$person ) {
try {
print 'Enter your age : ';
my $age = <STDIN>;
chomp $age;
print 'Enter your name : ';
my $name = <STDIN>;
chomp $name;
$person = Person->new(
age => $age,
name => $name
);
my $person_name = $person->name;
my $person_age = $person->age;
print "$person_name is $person_age years old\n";
}
catch {
my $e = $_;
if (
blessed $e
&& $e->isa(
'Moose::Exception::ValidationFailedForTypeConstraint')
) {
my $attribute_name = $e->attribute->name;
my $type_name = $e->type->name;
my $value = $e->value;
warn
"You entered $value for $attribute_name, which is not a $type_name!";
}
else {
warn "$e\n";
}
};
}
=head2 Example of catching AttributeIsRequired
use warnings;
use strict;
use Try::Tiny;
{
package Example::RequiredAttribute;
use Moose;
has required_attribute => (
is => 'ro',
isa => 'Int',
required => 1
);
}
try {
# we're not passing required_attribute, so it'll throw an exception
my $object = Example::RequiredAttribute->new();
}
catch {
my $e = $_;
if ( blessed $e && $e->isa('Moose::Exception::AttributeIsRequired') )
{
warn $e->message, "\n";
}
else {
warn "$e\n";
}
};
=head1 MOOSE EXCEPTION CLASSES
All the exception classes are listed in L<Moose::Manual::Exceptions::Manifest>.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

File diff suppressed because it is too large Load Diff

470
CPAN/Moose/Manual/FAQ.pod Normal file
View File

@@ -0,0 +1,470 @@
# PODNAME: Moose::Manual::FAQ
# ABSTRACT: Frequently asked questions about Moose
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::FAQ - Frequently asked questions about Moose
=head1 VERSION
version 2.2207
=head1 FREQUENTLY ASKED QUESTIONS
=head2 Module Stability
=head3 Is Moose "production ready"?
Yes! Many sites with household names are using Moose to build
high-traffic services. Countless others are using Moose in production.
See L<http://moose.iinteractive.com/about.html#organizations> for
a partial list.
As of this writing, Moose is a dependency of several hundred CPAN
modules. L<https://metacpan.org/requires/module/Moose>
=head3 Is Moose's API stable?
Yes. The sugary API, the one 95% of users will interact with, is
B<very stable>. Any changes will be B<100% backwards compatible>.
The meta API is less set in stone. We reserve the right to tweak
parts of it to improve efficiency or consistency. This will not be
done lightly. We do perform deprecation cycles. We I<really>
do not like making ourselves look bad by breaking your code.
Submitting test cases is the best way to ensure that your code is not
inadvertently broken by refactoring.
=head3 I heard Moose is slow, is this true?
Again, this one is tricky, so Yes I<and> No.
Firstly, I<nothing> in life is free, and some Moose features do cost
more than others. It is also the policy of Moose to B<only charge you
for the features you use>, and to do our absolute best to not place
any extra burdens on the execution of your code for features you are
not using. Of course using Moose itself does involve some overhead,
but it is mostly compile time. At this point we do have some options
available for getting the speed you need.
Currently we provide the option of making your classes immutable as a
means of boosting speed. This will mean a slightly larger compile time
cost, but the runtime speed increase (especially in object
construction) is pretty significant. This can be done with the
following code:
MyClass->meta->make_immutable();
=head2 Constructors
=head3 How do I write custom constructors with Moose?
Ideally, you should never write your own C<new> method, and should use
Moose's other features to handle your specific object construction
needs. Here are a few scenarios, and the Moose way to solve them;
If you need to call initialization code post instance construction,
then use the C<BUILD> method. This feature is taken directly from Perl
6. Every C<BUILD> method in your inheritance chain is called (in the
correct order) immediately after the instance is constructed. This
allows you to ensure that all your superclasses are initialized
properly as well. This is the best approach to take (when possible)
because it makes subclassing your class much easier.
If you need to affect the constructor's parameters prior to the
instance actually being constructed, you have a number of options.
To change the parameter processing as a whole, you can use the
C<BUILDARGS> method. The default implementation accepts key/value
pairs or a hash reference. You can override it to take positional
args, or any other format
To change the handling of individual parameters, there are I<coercions> (See
the L<Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion> for a complete
example and explanation of coercions). With coercions it is possible to morph
argument values into the correct expected types. This approach is the most
flexible and robust, but does have a slightly higher learning curve.
=head3 How do I make non-Moose constructors work with Moose?
Usually the correct approach to subclassing a non-Moose class is
delegation. Moose makes this easy using the C<handles> keyword,
coercions, and C<lazy_build>, so subclassing is often not the ideal
route.
That said, if you really need to inherit from a non-Moose class, see
L<Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParent> for an example of how to do it,
or take a look at L<Moose::Manual::MooseX/"MooseX::NonMoose">.
=head2 Accessors
=head3 How do I tell Moose to use get/set accessors?
The easiest way to accomplish this is to use the C<reader> and
C<writer> attribute options:
has 'bar' => (
isa => 'Baz',
reader => 'get_bar',
writer => 'set_bar',
);
Moose will still take advantage of type constraints, triggers, etc.
when creating these methods.
If you do not like this much typing, and wish it to be a default for
your classes, please see L<MooseX::FollowPBP>. This extension will
allow you to write:
has 'bar' => (
isa => 'Baz',
is => 'rw',
);
Moose will create separate C<get_bar> and C<set_bar> methods instead
of a single C<bar> method.
If you like C<bar> and C<set_bar>, see
L<MooseX::SemiAffordanceAccessor>.
NOTE: This B<cannot> be set globally in Moose, as that would break
other classes which are built with Moose. You can still save on typing
by defining a new C<MyApp::Moose> that exports Moose's sugar and then
turns on L<MooseX::FollowPBP>. See
L<Moose::Cookbook::Extending::Mooseish_MooseSugar>.
=head3 How can I inflate/deflate values in accessors?
Well, the first question to ask is if you actually need both inflate
and deflate.
If you only need to inflate, then we suggest using coercions. Here is
some basic sample code for inflating a L<DateTime> object:
class_type 'DateTime';
coerce 'DateTime'
=> from 'Str'
=> via { DateTime::Format::MySQL->parse_datetime($_) };
has 'timestamp' => (is => 'rw', isa => 'DateTime', coerce => 1);
This creates a custom type for L<DateTime> objects, then attaches
a coercion to that type. The C<timestamp> attribute is then told
to expect a C<DateTime> type, and to try to coerce it. When a C<Str>
type is given to the C<timestamp> accessor, it will attempt to
coerce the value into a C<DateTime> object using the code in found
in the C<via> block.
For a more comprehensive example of using coercions, see the
L<Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion>.
If you need to deflate your attribute's value, the current best
practice is to add an C<around> modifier to your accessor:
# a timestamp which stores as
# seconds from the epoch
has 'timestamp' => (is => 'rw', isa => 'Int');
around 'timestamp' => sub {
my $next = shift;
my $self = shift;
return $self->$next unless @_;
# assume we get a DateTime object ...
my $timestamp = shift;
return $self->$next( $timestamp->epoch );
};
It is also possible to do deflation using coercion, but this tends to
get quite complex and require many subtypes. An example of this is
outside the scope of this document, ask on #moose or send a mail to
the list.
Still another option is to write a custom attribute metaclass, which
is also outside the scope of this document, but we would be happy to
explain it on #moose or the mailing list.
=head2 Method Modifiers
=head3 How can I affect the values in C<@_> using C<before>?
You can't, actually: C<before> only runs before the main method, and
it cannot easily affect the method's execution.
You similarly can't use C<after> to affect the return value of a
method.
We limit C<before> and C<after> because this lets you write more
concise code. You do not have to worry about passing C<@_> to the
original method, or forwarding its return value (being careful to
preserve context).
The C<around> method modifier has neither of these limitations, but is
a little more verbose.
Alternatively, the L<MooseX::Mangle> extension provides the
C<mangle_args> function, which does allow you to affect C<@_>.
=head3 Can I use C<before> to stop execution of a method?
Yes, but only if you throw an exception. If this is too drastic a
measure then we suggest using C<around> instead. The C<around> method
modifier is the only modifier which can gracefully prevent execution
of the main method. Here is an example:
around 'baz' => sub {
my $next = shift;
my ($self, %options) = @_;
unless ($options->{bar} eq 'foo') {
return 'bar';
}
$self->$next(%options);
};
By choosing not to call the C<$next> method, you can stop the
execution of the main method.
Alternatively, the L<MooseX::Mangle> extension provides the
C<guard> function, which will conditionally prevent execution
of the original method.
=head3 Why can't I see return values in an C<after> modifier?
As with the C<before> modifier, the C<after> modifier is simply called
I<after> the main method. It is passed the original contents of C<@_>
and B<not> the return values of the main method.
Again, the arguments are too lengthy as to why this has to be. And as
with C<before> I recommend using an C<around> modifier instead. Here
is some sample code:
around 'foo' => sub {
my $next = shift;
my ($self, @args) = @_;
my @rv = $next->($self, @args);
# do something silly with the return values
return reverse @rv;
};
Alternatively, the L<MooseX::Mangle> extension provides the
C<mangle_return> function, which allows modifying the return values
of the original method.
=head2 Type Constraints
=head3 How can I provide a custom error message for a type constraint?
Use the C<message> option when building the subtype:
subtype 'NaturalLessThanTen'
=> as 'Natural'
=> where { $_ < 10 }
=> message { "This number ($_) is not less than ten!" };
This C<message> block will be called when a value fails to pass the
C<NaturalLessThanTen> constraint check.
=head3 Can I turn off type constraint checking?
There's no support for it in the core of Moose yet. This option may
come in a future release.
Meanwhile there's a L<MooseX
extension|MooseX::Attribute::TypeConstraint::CustomizeFatal> that
allows you to do this on a per-attribute basis, and if it doesn't do
what you it's easy to write one that fits your use case.
=head3 My coercions stopped working with recent Moose, why did you break it?
Moose 0.76 fixed a case where coercions were being applied even if the original
constraint passed. This has caused some edge cases to fail where people were
doing something like
subtype 'Address', as 'Str';
coerce 'Address', from 'Str', via { get_address($_) };
This is not what they intended, because the type constraint C<Address> is too
loose in this case. It is saying that all strings are Addresses, which is
obviously not the case. The solution is to provide a C<where> clause that
properly restricts the type constraint:
subtype 'Address', as 'Str', where { looks_like_address($_) };
This will allow the coercion to apply only to strings that fail to look like an
Address.
=head2 Roles
=head3 Why is BUILD not called for my composed roles?
C<BUILD> is never called in composed roles. The primary reason is that
roles are B<not> order sensitive. Roles are composed in such a way
that the order of composition does not matter (for information on the
deeper theory of this read the original traits papers here
L<http://www.iam.unibe.ch/~scg/Research/Traits/>).
Because roles are essentially unordered, it would be impossible to
determine the order in which to execute the C<BUILD> methods.
As for alternate solutions, there are a couple.
=over 4
=item *
Using a combination of lazy and default in your attributes to defer
initialization (see the Binary Tree example in the cookbook for a good example
of lazy/default usage
L<Moose::Cookbook::Basics::BinaryTree_AttributeFeatures>)
=item *
Use attribute triggers, which fire after an attribute is set, to
facilitate initialization. These are described in the L<Moose> docs,
and examples can be found in the test suite.
=back
In general, roles should not I<require> initialization; they should
either provide sane defaults or should be documented as needing
specific initialization. One such way to "document" this is to have a
separate attribute initializer which is required for the role. Here is
an example of how to do this:
package My::Role;
use Moose::Role;
has 'height' => (
is => 'rw',
isa => 'Int',
lazy => 1,
default => sub {
my $self = shift;
$self->init_height;
}
);
requires 'init_height';
In this example, the role will not compose successfully unless the
class provides a C<init_height> method.
If none of those solutions work, then it is possible that a role is
not the best tool for the job, and you really should be using
classes. Or, at the very least, you should reduce the amount of
functionality in your role so that it does not require initialization.
=head3 What are traits, and how are they different from roles?
In Moose, a trait is almost exactly the same thing as a role, except
that traits typically register themselves, which allows you to refer
to them by a short name ("Big" vs "MyApp::Role::Big").
In Moose-speak, a I<Role> is usually composed into a I<class> at
compile time, whereas a I<Trait> is usually composed into an instance
of a class at runtime to add or modify the behavior of B<just that
instance>.
Outside the context of Moose, traits and roles generally mean exactly
the same thing. The original paper called them traits, but Perl 6
will call them roles.
=head3 Can an attribute-generated method (e.g. an accessor) satisfy requires?
Yes, just be sure to consume the role I<after> declaring your
attribute. L<Moose::Manual::Roles/Required Attributes> provides
an example:
package Breakable;
use Moose::Role;
requires 'stress';
package Car;
use Moose;
has 'stress' => ( is => 'rw', isa => 'Int' );
with 'Breakable';
If you mistakenly consume the C<Breakable> role before declaring your
C<stress> attribute, you would see an error like this:
'Breakable' requires the method 'stress' to be implemented by 'Car' at...
=head2 Moose and Subroutine Attributes
=head3 Why don't subroutine attributes I inherited from a superclass work?
Currently when subclassing a module is done at runtime with the
C<extends> keyword, but attributes are checked at compile time by
Perl. To make attributes work, you must place C<extends> in a C<BEGIN>
block so that the attribute handlers will be available at compile time,
like this:
BEGIN { extends qw/Foo/ }
Note that we're talking about Perl's subroutine attributes here, not
Moose attributes:
sub foo : Bar(27) { ... }
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

214
CPAN/Moose/Manual/MOP.pod Normal file
View File

@@ -0,0 +1,214 @@
# PODNAME: Moose::Manual::MOP
# ABSTRACT: The Moose (and Class::MOP) meta API
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::MOP - The Moose (and Class::MOP) meta API
=head1 VERSION
version 2.2207
=head1 INTRODUCTION
Moose provides a powerful introspection API built on top of
C<Class::MOP>. "MOP" stands for Meta-Object Protocol. In plainer
English, a MOP is an API for performing introspection on classes,
attributes, methods, and so on.
In fact, it is C<Class::MOP> that provides many of Moose's core
features, including attributes, before/after/around method modifiers,
and immutability. In most cases, Moose takes an existing C<Class::MOP>
class and subclasses it to add additional features. Moose also adds
some entirely new features of its own, such as roles, the augment
modifier, and types.
If you're interested in the MOP, it's important to know about
C<Class::MOP> so you know what docs to read. Often, the introspection
method that you're looking for is defined in a C<Class::MOP> class,
rather than Moose itself.
The MOP provides more than just I<read-only> introspection. It also
lets you add attributes and methods, apply roles, and much more. In
fact, all of the declarative Moose sugar is simply a thin layer on top
of the MOP API.
If you want to write Moose extensions, you'll need to learn some of
the MOP API. The introspection methods are also handy if you want to
generate docs or inheritance graphs, or do some other runtime
reflection.
This document is not a complete reference for the meta API. We're just
going to cover some of the highlights, and give you a sense of how it
all works. To really understand it, you'll have to read a lot of other
docs, and possibly even dig into the Moose guts a bit.
=head1 GETTING STARTED
The usual entry point to the meta API is through a class's metaclass
object, which is a L<Moose::Meta::Class>. This is available by calling
the C<meta> method on a class or object:
package User;
use Moose;
my $meta = __PACKAGE__->meta;
The C<meta> method is added to a class when it uses Moose.
You can also use C<< Class::MOP::Class->initialize($name) >> to get a
metaclass object for any class. This is safer than calling C<<
$class->meta >> when you're not sure that the class has a meta method.
The C<< Class::MOP::Class->initialize >> constructor will return an
existing metaclass if one has already been created (via Moose or some
other means). If it hasn't, it will return a new C<Class::MOP::Class>
object. This will work for classes that use Moose, meta API classes,
and classes which don't use Moose at all.
=head1 USING THE METACLASS OBJECT
The metaclass object can tell you about a class's attributes, methods,
roles, parents, and more. For example, to look at all of the class's
attributes:
for my $attr ( $meta->get_all_attributes ) {
print $attr->name, "\n";
}
The C<get_all_attributes> method is documented in
C<Class::MOP::Class>. For Moose-using classes, it returns a list of
L<Moose::Meta::Attribute> objects for attributes defined in the class
and its parents.
You can also get a list of methods:
for my $method ( $meta->get_all_methods ) {
print $method->fully_qualified_name, "\n";
}
Now we're looping over a list of L<Moose::Meta::Method> objects. Note
that some of these objects may actually be a subclass of
L<Moose::Meta::Method>, as Moose uses different classes to represent
wrapped methods, delegation methods, constructors, etc.
We can look at a class's parent classes and subclasses:
for my $class ( $meta->linearized_isa ) {
print "$class\n";
}
for my $subclass ( $meta->subclasses ) {
print "$subclass\n";
}
Note that both these methods return class I<names>, not metaclass
objects.
=head1 ALTERING CLASSES WITH THE MOP
The metaclass object can change the class directly, by adding
attributes, methods, etc.
As an example, we can add a method to a class:
$meta->add_method( 'say' => sub { print @_, "\n" } );
Or an attribute:
$meta->add_attribute( 'size' => ( is => 'rw', isa => 'Int' ) );
Obviously, this is much more cumbersome than using Perl syntax or
Moose sugar for defining methods and attributes, but this API allows
for very powerful extensions.
You might remember that we've talked about making classes immutable
elsewhere in the manual. This is a good practice. However, once a
class is immutable, calling any of these update methods will throw an
exception.
You can make a class mutable again simply by calling C<<
$meta->make_mutable >>. Once you're done changing it, you can
restore immutability by calling C<< $meta->make_immutable >>.
However, the most common use for this part of the meta API is as
part of Moose extensions. These extensions should assume that they are
being run before you make a class immutable.
=head1 GOING FURTHER
If you're interested in extending Moose, we recommend reading all of
the "Meta" and "Extending" recipes in the L<Moose::Cookbook>. Those
recipes show various practical applications of the MOP.
If you'd like to write your own extensions, one of the best ways to
learn more about this is to look at other similar extensions to see
how they work. You'll probably also need to read various API docs,
including the docs for the various C<Moose::Meta::*> and
C<Class::MOP::*> classes.
Finally, we welcome questions on the Moose mailing list and
IRC. Information on the mailing list, IRC, and more references can be
found in the L<Moose.pm docs|Moose/GETTING HELP>.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,449 @@
# PODNAME: Moose::Manual::MethodModifiers
# ABSTRACT: Moose's method modifiers
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::MethodModifiers - Moose's method modifiers
=head1 VERSION
version 2.2207
=head1 WHAT IS A METHOD MODIFIER?
Moose provides a feature called "method modifiers". You can also think
of these as "hooks" or "advice".
It's probably easiest to understand this feature with a few examples:
package Example;
use Moose;
sub foo {
print " foo\n";
}
before 'foo' => sub { print "about to call foo\n"; };
after 'foo' => sub { print "just called foo\n"; };
around 'foo' => sub {
my $orig = shift;
my $self = shift;
print " I'm around foo\n";
$self->$orig(@_);
print " I'm still around foo\n";
};
Now if I call C<< Example->new->foo >> I'll get the following output:
about to call foo
I'm around foo
foo
I'm still around foo
just called foo
You probably could have figured that out from the names "before",
"after", and "around".
Also, as you can see, the before modifiers come before around
modifiers, and after modifiers come last.
When there are multiple modifiers of the same type, the before and
around modifiers run from the last added to the first, and after
modifiers run from first added to last:
before 2
before 1
around 2
around 1
primary
around 1
around 2
after 1
after 2
=head1 WHY USE THEM?
Method modifiers have many uses. They are often used in roles to alter the
behavior of methods in the classes that consume the role. See
L<Moose::Manual::Roles> for more information about roles.
Since modifiers are mostly useful in roles, some of the examples below
are a bit artificial. They're intended to give you an idea of how
modifiers work, but may not be the most natural usage.
=head1 BEFORE, AFTER, AND AROUND
Method modifiers can be used to add behavior to methods without modifying the definition of those methods.
=head2 Before and after Modifiers
Method modifiers can be used to add behavior to a method that Moose
generates for you, such as an attribute accessor:
has 'size' => ( is => 'rw' );
before 'size' => sub {
my $self = shift;
if (@_) {
Carp::cluck('Someone is setting size');
}
};
Another use for the before modifier would be to do some sort of
prechecking on a method call. For example:
before 'size' => sub {
my $self = shift;
die 'Cannot set size while the person is growing'
if @_ && $self->is_growing;
};
This lets us implement logical checks that don't make sense as type
constraints. In particular, they're useful for defining logical rules
about an object's state changes.
Similarly, an after modifier could be used for logging an action that
was taken.
Note that the return values of both before and after modifiers are
ignored.
=head2 Around modifiers
An around modifier is more powerful than either a before or
after modifier. It can modify the arguments being passed to the
original method, and you can even decide to simply not call the
original method at all. You can also modify the return value with an
around modifier.
An around modifier receives the original method as its first argument,
I<then> the object, and finally any arguments passed to the method.
around 'size' => sub {
my $orig = shift;
my $self = shift;
return $self->$orig()
unless @_;
my $size = shift;
$size = $size / 2
if $self->likes_small_things();
return $self->$orig($size);
};
=head2 Wrapping multiple methods at once
C<before>, C<after>, and C<around> can also modify multiple methods
at once. The simplest example of this is passing them as a list:
before [qw(foo bar baz)] => sub {
warn "something is being called!";
};
This will add a C<before> modifier to each of the C<foo>, C<bar>,
and C<baz> methods in the current class, just as though a separate
call to C<before> was made for each of them. The list can be passed
either as a bare list, or as an arrayref. Note that the name of the
function being modified isn't passed in in any way; this syntax is
only intended for cases where the function being modified doesn't
actually matter. If the function name does matter, use something like this:
for my $func (qw(foo bar baz)) {
before $func => sub {
warn "$func was called!";
};
}
=head2 Using regular expressions to select methods to wrap
In addition, you can specify a regular expression to indicate the
methods to wrap, like so:
after qr/^command_/ => sub {
warn "got a command";
};
This will match the regular expression against each method name
returned by L<Class::MOP::Class/get_method_list>, and add a modifier
to each one that matches. The same caveats apply as above.
Using regular expressions to determine methods to wrap is quite a bit more
powerful than the previous alternatives, but it's also quite a bit more
dangerous. Bear in mind that if your regular expression matches certain Perl
and Moose reserved method names with a special meaning to Moose or Perl, such
as C<meta>, C<new>, C<BUILD>, C<DESTROY>, C<AUTOLOAD>, etc, this could cause
unintended (and hard to debug) problems and is best avoided.
=head2 Execution order of method modifiers and inheritance
When both a superclass and an inheriting class have the same method modifiers,
the method modifiers of the inheriting class are wrapped around the method
modifiers of the superclass, as the following example illustrates:
Here is the parent class:
package Superclass;
use Moose;
sub rant { printf " RANTING!\n" }
before 'rant' => sub { printf " In %s before\n", __PACKAGE__ };
after 'rant' => sub { printf " In %s after\n", __PACKAGE__ };
around 'rant' => sub {
my $orig = shift;
my $self = shift;
printf " In %s around before calling original\n", __PACKAGE__;
$self->$orig;
printf " In %s around after calling original\n", __PACKAGE__;
};
1;
And the child class:
package Subclass;
use Moose;
extends 'Superclass';
before 'rant' => sub { printf "In %s before\n", __PACKAGE__ };
after 'rant' => sub { printf "In %s after\n", __PACKAGE__ };
around 'rant' => sub {
my $orig = shift;
my $self = shift;
printf " In %s around before calling original\n", __PACKAGE__;
$self->$orig;
printf " In %s around after calling original\n", __PACKAGE__;
};
1;
And here's the output when we call the wrapped method (C<< Child->rant >>):
% perl -MSubclass -e 'Subclass->new->rant'
In Subclass before
In Subclass around before calling original
In Superclass before
In Superclass around before calling original
RANTING!
In Superclass around after calling original
In Superclass after
In Subclass around after calling original
In Subclass after
=head1 INNER AND AUGMENT
Augment and inner are two halves of the same feature. The augment
modifier provides a sort of inverted subclassing. You provide part of
the implementation in a superclass, and then document that subclasses
are expected to provide the rest.
The superclass calls C<inner()>, which then calls the C<augment>
modifier in the subclass:
package Document;
use Moose;
sub as_xml {
my $self = shift;
my $xml = "<document>\n";
$xml .= inner();
$xml .= "</document>\n";
return $xml;
}
Using C<inner()> in this method makes it possible for one or more
subclasses to then augment this method with their own specific
implementation:
package Report;
use Moose;
extends 'Document';
augment 'as_xml' => sub {
my $self = shift;
my $xml = " <report>\n";
$xml .= inner();
$xml .= " </report>\n";
return $xml;
};
When we call C<as_xml> on a Report object, we get something like this:
<document>
<report>
</report>
</document>
But we also called C<inner()> in C<Report>, so we can continue
subclassing and adding more content inside the document:
package Report::IncomeAndExpenses;
use Moose;
extends 'Report';
augment 'as_xml' => sub {
my $self = shift;
my $xml = ' <income>' . $self->income . '</income>';
$xml .= "\n";
$xml .= ' <expenses>' . $self->expenses . '</expenses>';
$xml .= "\n";
$xml .= inner() || q{};
return $xml;
};
Now our report has some content:
<document>
<report>
<income>$10</income>
<expenses>$8</expenses>
</report>
</document>
What makes this combination of C<augment> and C<inner()> special is
that it allows us to have methods which are called from parent (least
specific) to child (most specific). This inverts the normal
inheritance pattern.
Note that in C<Report::IncomeAndExpenses> we call C<inner()> again. If the
object is an instance of C<Report::IncomeAndExpenses> then this call is a
no-op, and just returns false. It's a good idea to always call C<inner()> to
allow for future subclassing.
=head1 OVERRIDE AND SUPER
Finally, Moose provides some simple sugar for Perl's built-in method
overriding scheme. If you want to override a method from a parent
class, you can do this with C<override>:
package Employee;
use Moose;
extends 'Person';
has 'job_title' => ( is => 'rw' );
override 'display_name' => sub {
my $self = shift;
return super() . q{, } . $self->job_title();
};
The call to C<super()> is almost the same as calling C<<
$self->SUPER::display_name >>. The difference is that the arguments
passed to the superclass's method will always be the same as the ones
passed to the method modifier, and cannot be changed.
All arguments passed to C<super()> are ignored, as are any changes
made to C<@_> before C<super()> is called.
=head1 SEMI-COLONS
Because all of these method modifiers are implemented as Perl
functions, you must always end the modifier declaration with a
semi-colon:
after 'foo' => sub { };
=head1 EXCEPTIONS AND STACK TRACES
An exception thrown in a C<before> modifier will prevent the method it
modifies from being called at all. An exception in an C<around> modifier may
prevent the modified method from being called, depending on how the C<around>
modifier is structured. An exception in an C<after> modifier obviously cannot
prevent the method it wraps from being called.
Both C<override> and C<augment> are similar to C<around> in that they can
decide whether or not to call the method they modify before or after throwing
an exception.
From the caller's perspective, an exception in a method modifier will look
like the method it called threw an exception. However, method modifiers are
just standard Perl subroutines. This means that they end up on the stack in
stack traces as an additional frame.
=head1 CAVEATS
These method modification features do not work well with multiple inheritance,
due to how method resolution is performed in Perl. Experiment with a test
program to ensure your class hierarchy works as expected, or more preferably,
don't use multiple inheritance (roles can help with this)!
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,326 @@
# PODNAME: Moose::Manual::MooseX
# ABSTRACT: Recommended Moose extensions
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::MooseX - Recommended Moose extensions
=head1 VERSION
version 2.2207
=head1 MooseX?
It's easy to extend and change Moose, and this is part of what makes
Moose so powerful. You can use the MOP API to do things your own way,
add new features, and generally customize your Moose.
Writing your own extensions does require a good understanding of the
meta-model. You can start learning about this with the
L<Moose::Manual::MOP> docs. There are also several extension recipes
in the L<Moose::Cookbook>.
Explaining how to write extensions is beyond the scope of this
manual. Fortunately, lots of people have already written extensions
and put them on CPAN for you.
This document covers a few of the ones we like best.
=head1 L<MooseX::AttributeHelpers>
The functionality of this MooseX module has been moved into Moose core.
See L<Moose::Meta::Attribute::Native>.
=head1 L<Moose::Autobox>
MooseX::AttributeHelpers, but turned inside out, Moose::Autobox provides
methods on both arrays/hashes/etc. but also references to them, using
Moose roles, allowing you do to things like:
use Moose::Autobox;
$somebody_elses_object->orders->push($order);
Lexically scoped and not to everybody's taste, but very handy for sugaring
up other people's APIs and your own code.
=head1 L<MooseX::StrictConstructor>
By default, Moose lets you pass any old junk into a class's
constructor. If you load L<MooseX::StrictConstructor>, your class will
throw an error if it sees something it doesn't recognize;
package User;
use Moose;
use MooseX::StrictConstructor;
has 'name';
has 'email';
User->new( name => 'Bob', emali => 'bob@example.com' );
With L<MooseX::StrictConstructor>, that typo ("emali") will cause a
runtime error. With plain old Moose, the "emali" attribute would be
silently ignored.
=head1 L<MooseX::Params::Validate>
We have high hopes for the future of L<MooseX::Method::Signatures> and
L<Moops>. However, these modules, while used regularly in
production by some of the more insane members of the community, are
still marked alpha just in case backwards incompatible changes need to
be made.
If you don't want to risk that, for now we recommend the decidedly more
clunky (but also faster and simpler) L<MooseX::Params::Validate>. This
module lets you apply Moose types and coercions to any method
arguments.
package User;
use Moose;
use MooseX::Params::Validate;
sub login {
my $self = shift;
my ($password)
= validated_list( \@_, password => { isa => 'Str', required => 1 } );
...
}
=head1 L<MooseX::Getopt>
This is a role which adds a C<new_with_options> method to your
class. This is a constructor that takes the command line options and
uses them to populate attributes.
This makes writing a command-line application as a module trivially
simple:
package App::Foo;
use Moose;
with 'MooseX::Getopt';
has 'input' => (
is => 'ro',
isa => 'Str',
required => 1
);
has 'output' => (
is => 'ro',
isa => 'Str',
required => 1
);
sub run { ... }
Then in the script that gets run we have:
use App::Foo;
App::Foo->new_with_options->run;
From the command line, someone can execute the script:
foo@example> foo --input /path/to/input --output /path/to/output
=head1 L<MooseX::Singleton>
To be honest, using a singleton is just a way to have a magic global
variable in languages that don't actually have global variables.
In perl, you can just as easily use a global. However, if your
colleagues are Java-infected, they might prefer a singleton. Also, if
you have an existing class that I<isn't> a singleton but should be,
using L<MooseX::Singleton> is the easiest way to convert it.
package Config;
use MooseX::Singleton; # instead of Moose
has 'cache_dir' => ( ... );
It's that simple.
=head1 EXTENSIONS TO CONSIDER
There are literally dozens of other extensions on CPAN. This is a list
of extensions that you might find useful, but we're not quite ready to
endorse just yet.
=head2 L<MooseX::Declare>
MooseX::Declare is based on L<Devel::Declare>, a giant bag of crack
originally implemented by mst with the goal of upsetting the perl core
developers so much by its very existence that they implemented proper
keyword handling in the core.
As of perl5 version 14, this goal has been achieved, and modules such
as L<Devel::CallParser>, L<Function::Parameters>, and L<Keyword::Simple> provide
mechanisms to mangle perl syntax that don't require hallucinogenic
drugs to interpret the error messages they produce.
If you want to use declarative syntax in new code, please for the love
of kittens get yourself a recent perl and look at L<Moops> instead.
=head2 L<MooseX::Types>
This extension helps you build a type library for your application. It
also lets you predeclare type names and use them as barewords.
use MooseX::Types -declare => ['PositiveInt'];
use MooseX::Types::Moose 'Int';
subtype PositiveInt,
as Int,
where { $_ > 0 },
message { "Int is not larger than 0" };
One nice feature is that those bareword names are actually namespaced
in Moose's type registry, so multiple applications can use the same
bareword names, even if the type definitions differ.
=head2 L<MooseX::Types::Structured>
This extension builds on top of L<MooseX::Types> to let you declare
complex data structure types.
use MooseX::Types -declare => [ qw( Name Color ) ];
use MooseX::Types::Moose qw(Str Int);
use MooseX::Types::Structured qw(Dict Tuple Optional);
subtype Name
=> as Dict[ first => Str, middle => Optional[Str], last => Str ];
subtype Color
=> as Tuple[ Int, Int, Int, Optional[Int] ];
Of course, you could always use objects to represent these sorts of
things too.
=head2 L<MooseX::ClassAttribute>
This extension provides class attributes for Moose classes. The
declared class attributes are introspectable just like regular Moose
attributes.
package User;
use Moose;
use MooseX::ClassAttribute;
has 'name' => ( ... );
class_has 'Cache' => ( ... );
Note however that this class attribute does I<not> inherit like a
L<Class::Data::Inheritable> or similar attribute - calling
$subclass->Cache($cache);
will set it for the superclass as well. Additionally, class data is usually
The Wrong Thing To Do in a strongly OO program since it makes testing a
lot harder - consider carefully whether you'd be better off with an object
that's passed around instead.
=head2 L<MooseX::Daemonize>
This is a role that provides a number of methods useful for creating a
daemon, including methods for starting and stopping, managing a PID
file, and signal handling.
=head2 L<MooseX::Role::Parameterized>
If you find yourself wanting a role that customizes itself for each
consumer, this is the tool for you. With this module, you can create a
role that accepts parameters and generates attributes, methods, etc. on
a customized basis for each consumer.
=head2 L<MooseX::POE>
This is a small wrapper that ties together a Moose class with
C<POE::Session>, and gives you an C<event> sugar function to declare
event handlers.
=head2 L<MooseX::FollowPBP>
Automatically names all accessors I<Perl Best Practices>-style,
"get_size" and "set_size".
=head2 L<MooseX::SemiAffordanceAccessor>
Automatically names all accessors with an explicit set and implicit
get, "size" and "set_size".
=head2 L<MooseX::NonMoose>
MooseX::NonMoose allows for easily subclassing non-Moose classes with Moose,
taking care of the annoying details connected with doing this, such as
setting up proper inheritance from Moose::Object and installing
(and inlining, at make_immutable time) a constructor that makes sure things
like BUILD methods are called.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,526 @@
# PODNAME: Moose::Manual::Resources
# ABSTRACT: Links to various tutorials, videos, blogs, presentations, interviews, etc...
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Resources - Links to various tutorials, videos, blogs, presentations, interviews, etc...
=head1 VERSION
version 2.2207
=head1 Resources
This section is an attempt to collect and list some of the many Moose resources that can be found online. Additional information can be found at http://moose.perl.org/
=head2 Videos
=over 4
=item
A new object system for the Perl 5 core, Stevan Little
L<https://www.youtube.com/watch?v=Gf0O6Ct7V1s>
=item
Stevan Little interviewed by Gabor Szabo for PerlMaven.com
L<https://www.youtube.com/watch?v=shu-bVimOpM>
=item
Perl 6 OO vs. Moose, Herbert Breunung
L<https://www.youtube.com/watch?v=Boh3109HVLo>
=item
Introduction To Moose, Mike Whitaker
L<https://www.youtube.com/watch?v=YVtqa6zWXqY>
=item
"Dr. Strange... Moose or: How I Learned to Stop Worrying and Love Perl"
L<https://www.youtube.com/watch?v=PNFiIU8S-7g>
=item
Evolving Software with Moose, Dave Cross
L<https://www.youtube.com/watch?v=BIMREkoPYKA>
=item
Testing with Test::Class::Moose, Curtis Poe
L<https://www.youtube.com/watch?v=kUHI1iRrfF4>
=item
"Moose is Perl" tutorial, OSCON 2014, Ricardo Signes
L<https://www.youtube.com/watch?v=LKXvG6VKew4>
=back
=head2 Slide Shows
=over 4
=item
Use Moose to create abstractions in the domain, Shawn M. Moore (sartak)
L<https://speakerdeck.com/sartak/lifting-moose>
=back
=head2 Articles
=over 4
=item
Perl.org Moose Whitepaper
L<https://www.perl.org/about/whitepapers/perl-object-oriented.html>
=item
PerlMaven.com
L<http://perlmaven.com/moose>
=item
Getting Started with Moose, brian d foy
http://www.theperlreview.com/articles/moose.html
=item
Wikipedia.org
L<http://en.wikipedia.org/wiki/Moose_(Perl)>
=item
Moose: A postmodern object system for Perl 5
L<http://perltraining.com.au/tips/2010-01-27.html>
=item
Roles and Delegates and Refactoring
L<http://blog.woobling.org/2009/10/roles-and-delegates-and-refactoring.html>
=back
=head1 Older Resources
=head2 Articles
=head3 2011
=over 4
=item
Dave Rolsky reviews Perl Best Practices, Chapter 15, Objects 7 years later
L<http://blog.urth.org/2011/03/reviewing-perl-best-practices-chapter-15-objects.html>
=item
Mark A. Stratman discusses subclassing non-Moose classes
L<http://blogs.perl.org/users/mark_a_stratman/2011/03/subclassing-tricky-non-moose-classes-constructor-problems.html>
=item
Mark A. Stratman shows how to use delegation to work with non-Moose classes
L<http://blogs.perl.org/users/mark_a_stratman/2011/03/subclassing-tricky-non-moose-classes-dont-do-it.html>
=item
The WebGUI folks talk about version 8.0 (which uses Moose)
L<http://blogs.perl.org/users/preaction/2011/01/whats-new-in-webgui-80-1---psgiplack.html>
=item
chromatic discusses Parameterized roles with Moose
L<http://www.modernperlbooks.com/mt/2011/01/the-parametric-role-of-my-mvc-plugin-system.html>
=back
=head3 2010
=over 4
=item
Chris Prather discusses Moose and the Modern Perl movement
L<http://chris.prather.org/been-there-done-that.md.html>
=item
Devin Austin talks about MooseX::App::Cmd
L<http://www.catalyzed.org/2010/04/moosexappcmd-and-your-command-line-apps.html>
=item
JT Smith declares The Second Age of Perl
L<http://blogs.perl.org/users/jt_smith/2010/04/the-second-age-of-perl.html>
=item
JT Smith talks about Lacuna Expanse (which uses Moose)
L<http://blogs.perl.org/users/jt_smith/2010/10/why-the-lacuna-expanse-is-good-for-perl.html>
=item
Moose 1.00 is Released
L<http://stevan-little.blogspot.com/2010/03/moose-100-is-released.html>
=item
Moritz Lenz asks What is "Modern Perl"?
L<http://perlgeek.de/blog-en/perl-tips/what-is-modern-perl.html>
=item
Yuval Kogman declares "Moose has won".
L<http://blog.woobling.org/2010/09/moose-has-won.html>
=item
chromatic discusses how Moose helps you write more correct code
L<http://www.modernperlbooks.com/mt/2010/01/subtle-encouragement-toward-correctness.html>
=item
chromatic discusses the Moose deprecation policy
L<http://www.modernperlbooks.com/mt/2010/09/the-right-approach-to-deprecation.html>
=item
chromatic talks about Class::MOP in relation to his Modern Perl book
L<http://www.modernperlbooks.com/mt/2010/03/ill-get-the-mop.html>
=item
chromatic talks about Encapsulation and Moose
L<http://www.modernperlbooks.com/mt/2010/09/what-you-can-and-cannot-teach-about-encapsulation.html>
=back
=head3 2009
=over 4
=item
Bruno Vecchi praises Moose for making his protein analysis code easier
L<http://zerothorder.blogspot.com/2009/04/chopping-proteins-with-moose.html>
=item
Chris Prather compares MooseX::Declare to Simula 67
L<http://chris.prather.org/a-little-bit-of-history.md.html>
=item
Chris Prather rationalizes Moose's "post modern" label
L<http://chris.prather.org/why-moose-is-post-modern.html>
=item
Dave Rolsky's post-mortem on his Moose documentation grant
L<http://blog.urth.org/2009/04/moose-docs-grant-wrap-up.html>
=item
David McLaughlin experiments with extending Moose for MooseX::ChainedAccessors
L<http://www.dmclaughlin.com/2009/05/15/chained-accessors-in-moose/>
=item
Sam Crawley summarizes his experience with roles
L<http://samcrawley.wordpress.com/2009/05/03/getting-the-hang-of-moose-roles/>
=item
Shawn M Moore discusses Perl::Critic for Moose and linting with the MOP
L<http://blog.sartak.org/2009/05/perl-critic-dynamic-moose.html>
=item
Shlomi Fish discovers a better way to Moose
L<http://community.livejournal.com/shlomif_tech/38407.html>
=item
Stevan Little explains why you should make your Moose classes immutable
L<http://stevan-little.blogspot.com/2009/06/why-makeimmutable-is-recommended-for_13.html>
=item
Tomas Doran interview about the new Moose-based Catalyst
L<http://www.catalyzed.org/2009/04/catalyst-58-released.html>
=item
chromatic contrasts roles and duck-typing
L<http://www.modernperlbooks.com/mt/2009/05/perl-roles-versus-duck-typing.html>
=item
chromatic contrasts roles and inheritance
L<http://www.modernperlbooks.com/mt/2009/05/perl-roles-versus-inheritance.html>
=item
chromatic on The Why of Perl Roles
L<http://www.modernperlbooks.com/mt/2009/04/the-why-of-perl-roles.html>
=back
=head3 2008
=over 4
=item
Barry Walsh does an excellent comparison of Moose and Ruby (specifically the Doodle module)
L<http://draegtun.wordpress.com/2008/03/12/doodling-with-moose-part-1/>
=item
Tim Bunce's excellent Perl Myths talk gives a shout out to Moose
L<http://www.slideshare.net/Tim.Bunce/perl-myths-200802-with-notes/>
=item
chromatic suggests Moose and Mouse in his Beginners Introduction to Object-Oriented Programming with Perl article
L<http://broadcast.oreilly.com/2008/11/beginners-introduction-to-obje.html>
=back
=head3 2007
=over 4
=item
Larry mentioned Moose in 2007's State of the Onion speech
L<http://www.perl.com/pub/a/2007/12/06/soto-11.html?page=3>
=item
Max Kanat-Alexander (of Bugzilla fame) has some nice things to say about Moose
L<http://avatraxiom.livejournal.com/70947.html>
=back
=head3 2006
=over 4
=item
Class::MOP Review (OnLAMP)
L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
=back
=head2 Presentations
=head3 Perl Mongers Groups
=over 4
=item
Doug Treder's Moose talk at Seattle Perl Users Group
L<http://www.slideshare.net/dtreder/moose-527243>
=item
Hans Dieter Pearcey's Meta-Moose at PDX.pm
L<http://www.weftsoar.net/~hdp/talk/meta-moose/slides/start.html>
=item
Piers Cawley's MooseX::Declare talk at London.pm (video)
L<http://www.bofh.org.uk/2009/05/13/london-pm-presentation>
=item
Robert Boone's Moose talk at Houston.pm
L<http://houston.pm.org/talks/2007talks/0704Talk/slides/start.html>
=item
hakobe's Moose presentation at Kansai.pm
L<http://www.slideshare.net/hakobe/moose>
=back
=head3 2011
=over 4
=item
SawyerX's FOSDEM 2011 Moose talk
L<http://www.slideshare.net/xSawyer/moose-talk-at-fosdem-2011-perl-devroom>
=back
=head3 2010
=over 4
=item
Drew Stephens gives a lighting talk on Moose at SHDH 36
L<http://www.slideshare.net/dinomite/learning-moose-lightning>
=item
Jesse Luehrs's "Extending Moose" talk at YAPC::NA 2010
L<http://tozt.net/talks/extending_moose_yapc_na_2010/>
=item
Shawn Moore's "Non-hierarchical osdc.tw
L<http://sartak.org/talks/osdc.tw-2010/nonhierarchical-oop/nonhierarchical-oop.pdf>
=item
Ynon Perek's Perl Object Oriented Programming slides
L<http://prezi.com/fgdoyw0smyqo/perl-object-oriented-programming/>
=back
=head3 2009
=over 4
=item
Dave Rolsky's Introduction to Moose master class at YAPC::NA 2009 (delivered by Shawn Moore and Jonathan Rockway)
L<http://yapc10.org/yn2009/talk/2047>
=item
Devin Austin's Intro to Moose at YAPC::NA 2009
L<http://yapc10.org/yn2009/talk/1967>
=item
Hans Dieter Pearcey's Code Reuse with Moose at YAPC::NA 2009
L<http://yapc10.org/yn2009/talk/1984>
=item
Mike Whitaker's Intro to Moose at Italian Perl Workshop
L<http://www.slideshare.net/Penfold/introduction-to-moose-2437037>
=item
Mike Whitaker's Introduction to Moose at the Italian Perl Workshop
L<http://conferences.yapceurope.org/ipw2009/talk/2371>
=item
Shawn M Moore's Intro to Moose at Frozen Perl
L<http://sartak.org/talks/frozen-perl-2009/moose/>
=item
Shawn Moore's Extending Moose for Applications at YAPC::NA 2009
L<http://sartak.org/talks/yapc-na-2009/extending-moose/extending-moose.pdf>
=item
Shawn Moore's Moose master class at YAPC::Asia 2009
L<http://conferences.yapcasia.org/ya2009/talk/2192>
=item
Yuval Kogman's Why Moose at the Nordic Perl Workshop
L<http://www.perlworkshop.no/npw2009/talk/1901>
=back
=head3 2008
=over 4
=item
Mike Whitaker's Intro to Moose at the London Perl Workshop
L<http://yapc.tv/2008/lpw/mike-whitaker-intro-moose/>
=back
=head3 2006
=over 4
=item
Sam Vilain gives the very first Moose talk at YAPC::EU
L<http://www.yapceurope.org/2006/talk/item/63.html>
=back
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

557
CPAN/Moose/Manual/Roles.pod Normal file
View File

@@ -0,0 +1,557 @@
# PODNAME: Moose::Manual::Roles
# ABSTRACT: Roles, an alternative to deep hierarchies and base classes
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Roles - Roles, an alternative to deep hierarchies and base classes
=head1 VERSION
version 2.2207
=head1 WHAT IS A ROLE?
A role encapsulates some piece of behavior or state that can be shared between
classes. It is something that classes I<do>. It is important to understand that
I<roles are not classes>. You cannot inherit from a role, and a role cannot be
instantiated. We sometimes say that roles are I<consumed>, either by classes
or other roles.
Instead, a role is I<composed> into a class. In practical terms, this
means that all of the methods, method modifiers, and attributes defined in a role are
added directly to (we sometimes say "flattened into") the class that
consumes the role. These attributes and methods then appear as if they
were defined in the class itself. A subclass of the consuming class
will inherit all of these methods and attributes.
Moose roles are similar to mixins or interfaces in other languages and are
based on the L<original concept of Traits|http://scg.unibe.ch/research/traits/>
for the Smalltalk-80 dialect Squeak.
Besides defining their own methods and attributes, roles can also
require that the consuming class define certain methods of its
own. You could have a role that consisted only of a list of required
methods, in which case the role would be very much like a Java
interface.
Note that attribute accessors also count as methods for the
purposes of satisfying the requirements of a role.
=head1 A SIMPLE ROLE
Creating a role looks a lot like creating a Moose class:
package Breakable;
use Moose::Role;
has 'is_broken' => (
is => 'rw',
isa => 'Bool',
);
sub break {
my $self = shift;
print "I broke\n";
$self->is_broken(1);
}
Except for our use of L<Moose::Role>, this looks just like a class
definition with Moose. However, this is not a class, and it cannot be
instantiated.
Instead, its attributes and methods will be composed into classes
which use the role:
package Car;
use Moose;
with 'Breakable';
has 'engine' => (
is => 'ro',
isa => 'Engine',
);
The C<with> function composes roles into a class. Once that is done,
the C<Car> class has an C<is_broken> attribute and a C<break>
method. The C<Car> class also C<does('Breakable')>:
my $car = Car->new( engine => Engine->new );
print $car->is_broken ? 'Busted' : 'Still working';
$car->break;
print $car->is_broken ? 'Busted' : 'Still working';
$car->does('Breakable'); # true
This prints:
Still working
I broke
Busted
We could use this same role in a C<Bone> class:
package Bone;
use Moose;
with 'Breakable';
has 'marrow' => (
is => 'ro',
isa => 'Marrow',
);
See also L<Moose::Cookbook::Roles::Comparable_CodeReuse> for an example.
It's possible to compose existing roles into new roles. For example, we can
have a C<HandleWithCare> class which applies both the C<Breakable> and
C<Package> roles to any class which consumes it:
package HandleWithCare;
use Moose::Role;
with 'Breakable', 'Package';
=head1 REQUIRED METHODS
As mentioned previously, a role can require that consuming classes
provide one or more methods. Using our C<Breakable> example, let's
make it require that consuming classes implement their own C<break>
methods:
package Breakable;
use Moose::Role;
requires 'break';
has 'is_broken' => (
is => 'rw',
isa => 'Bool',
);
after 'break' => sub {
my $self = shift;
$self->is_broken(1);
};
If we try to consume this role in a class that does not have a
C<break> method, we will get an exception.
You can see that we added a method modifier on C<break>. We want
classes that consume this role to implement their own logic for
breaking, but we make sure that the C<is_broken> attribute is always
set to true when C<break> is called.
package Car
use Moose;
with 'Breakable';
has 'engine' => (
is => 'ro',
isa => 'Engine',
);
sub break {
my $self = shift;
if ( $self->is_moving ) {
$self->stop;
}
}
=head2 Roles Versus Abstract Base Classes
If you are familiar with the concept of abstract base classes in other
languages, you may be tempted to use roles in the same way.
You I<can> define an "interface-only" role, one that contains I<just>
a list of required methods.
However, any class which consumes this role must implement all of the
required methods, either directly or through inheritance from a
parent. You cannot delay the method requirement check so that they can
be implemented by future subclasses.
Because the role defines the required methods directly, adding a base
class to the mix would not achieve anything. We recommend that you
simply consume the interface role in each class which implements that
interface.
=head1 CONSUMING ROLES
Roles are consumed using the C<with> function.
Most of the time, you should only use one C<with>, even if you are consuming
multiple roles. If you consume roles using multiple C<with> statements Moose
cannot detect method conflicts between those roles.
Roles can be consumed by classes or by other roles. When a class consumes a
role which in turn consumes other roles, the class gets all of the roles
applied at once.
=head2 Required Methods Provided by Attributes
As mentioned before, a role's required method may also be satisfied by an
attribute accessor. However, the call to C<has> which defines an attribute
happens at runtime. This means that you must define the attribute I<before>
consuming the role, or else the role will not see the generated accessor.
These attributes are L<Moose Attributes|Moose::Manual::Attributes>.
package Breakable;
use Moose::Role;
requires 'stress';
########
package Car;
use Moose;
has 'stress' => (
is => 'ro',
isa => 'Int',
);
with 'Breakable';
In general, we recommend that you always consume roles I<after> declaring all
your attributes.
It may also be the case that a class wants to consume two roles where one role
has an attribute providing a required method for another. For example:
package Breakable;
use Moose::Role;
requires 'stress';
########
package Stressable;
use Moose::Role;
has 'stress' => (
is => 'ro',
isa => 'Int',
);
########
package Car;
use Moose;
# XXX - this will not work
with 'Breakable', 'Stressable';
However, this won't work. The problem is that the accessor methods created for
the C<stress> attribute won't be present in the class when the required method
checks are done.
There are two possible workarounds. The recommended one is to use "stub"
subroutine(s) in the role providing the accessor(s):
package Stressable;
use Moose::Role;
sub stress;
has 'stress' => (
is => 'ro',
isa => 'Int',
);
The C<sub stress;> line is called a "forward" declaration in the Perl
documentation. It creates what is called a "stub" subroutine, a declaration
without a body. This is good enough to satisfy the required method checks done
by Moose. The stub will not interfere with the creation of a real subroutine
later.
The other alternative is to use two separate calls to C<with> in the consuming
class:
package Car;
use Moose;
# Not recommended
with 'Stressable';
with 'Breakable';
Each C<with> is run as it is seen. The first call will consume just the
C<Stressable> role, which will add the C<stress> attribute to the C<Car>
package, which in turn will create an accessor method named C<stress>. Then
when the C<Breakable> role is consumed, the method it requires already exists.
However, as mentioned earlier, multiple C<with> declarations are not
recommended, because method conflicts between the roles cannot be seen. In the
example above, if both C<Stressable> and C<Breakable> contained methods of the
same name, what would happen is that the version in C<Stressable> would
I<silently> override the one in C<Breakable>.
=head1 USING METHOD MODIFIERS
Method modifiers and roles are a very powerful combination. Often, a
role will combine method modifiers and required methods. We already
saw one example with our C<Breakable> example.
Method modifiers increase the complexity of roles, because they make
the role application order relevant. If a class uses multiple roles,
each of which modify the same method, those modifiers will be applied
in the same order as the roles are used:
package MovieCar;
use Moose;
extends 'Car';
with 'Breakable', 'ExplodesOnBreakage';
Assuming that the new C<ExplodesOnBreakage> role I<also> has an
C<after> modifier on C<break>, the C<after> modifiers will run one
after the other. The modifier from C<Breakable> will run first, then
the one from C<ExplodesOnBreakage>.
=head1 METHOD CONFLICTS
If a class composes multiple roles, and those roles have methods of
the same name, we will have a conflict. In that case, the composing
class is required to provide its I<own> method of the same name.
package Breakdancer;
use Moose::Role;
sub break {
}
If we compose both C<Breakable> and C<Breakdancer> in a class, we must
provide our own C<break> method:
package FragileDancer;
use Moose;
with 'Breakable', 'Breakdancer';
sub break { ... }
A role can be a collection of other roles:
package Break::Bundle;
use Moose::Role;
with ('Breakable', 'Breakdancer');
When a role consumes another a role, the I<consuming> role's methods silently
win in any conflict, and the consumed role's methods are simply ignored.
=head1 METHOD EXCLUSION AND ALIASING
If we want our C<FragileDancer> class to be able to call the methods
from both its roles, we can alias the methods:
package FragileDancer;
use Moose;
with 'Breakable' => { -alias => { break => 'break_bone' } },
'Breakdancer' => { -alias => { break => 'break_dance' } };
However, aliasing a method simply makes a I<copy> of the method with
the new name. We also need to exclude the original name:
with 'Breakable' => {
-alias => { break => 'break_bone' },
-excludes => 'break',
},
'Breakdancer' => {
-alias => { break => 'break_dance' },
-excludes => 'break',
};
The excludes parameter prevents the C<break> method from being composed
into the C<FragileDancer> class, so we don't have a conflict. This
means that C<FragileDancer> does not need to implement its own
C<break> method.
This is useful, but it's worth noting that this breaks the contract
implicit in consuming a role. Our C<FragileDancer> class does both the
C<Breakable> and C<BreakDancer>, but does not provide a C<break>
method. If some API expects an object that does one of those roles, it
probably expects it to implement that method.
In some use cases we might alias and exclude methods from roles, but
then provide a method of the same name in the class itself.
Also see L<Moose::Cookbook::Roles::Restartable_AdvancedComposition> for an example.
=head1 OVERLOADING
When a Moose role uses overloading, that overloading is composed into any
classes that consume the role. This includes the setting of the C<fallback>
value for that role's overloading. Just as with methods and attributes, when a
role consumes another role, that other role's overloading settings are applied
to the role.
Just as with methods, there can be conflicts with overloading implementations
between multiple roles when they are all consumed by a class. If two roles
both provide different overloading implementations for a given operator, that
is a conflict. If two roles both implement overloading and have different
C<fallback> values, that is also considered a conflict. These conflicts are
detected when multiple roles are being composed into a class together.
When a role consumes another role, the consuming role's overloading fallback
and operator implementations silently "win" the conflict.
=head1 ROLE EXCLUSION
A role can say that it cannot be combined with some other role. This
should be used with great caution, since it limits the re-usability of
the role.
package Breakable;
use Moose::Role;
excludes 'BreakDancer';
=head1 ADDING A ROLE TO AN OBJECT INSTANCE
You may want to add a role to an object instance, rather than to a class. For
example, you may want to add debug tracing to one instance of an object while
debugging a particular bug. Another use case might be to dynamically change
objects based on a user's configuration, as a plugin system.
The best way to do this is to use the C<apply_all_roles()> function from
L<Moose::Util>:
use Moose::Util qw( apply_all_roles );
my $car = Car->new;
apply_all_roles( $car, 'Breakable' );
This function can apply more than one role at a time, and will do so using the
normal Moose role combination system. We recommend using this function to
apply roles to an object. This is what Moose uses internally when you call
C<with>.
=head2 Handling required attributes for roles.
Application of some roles will require additional parameters being specified to
satisfy them, for example:
{
package Car;
use Moose;
}
{
package Breakable;
use Moose::Role;
has 'breakable_parts' => ( is => 'ro', required => 1 );
}
my $car = Car->new;
# next line dies with: Attribute (breakable_parts) is required
apply_all_roles( $car, 'Breakable' );
This will require passing the additional parameters at application time as
follows:
apply_all_roles( $car, 'Breakable' => {
rebless_params => {
# Parameters to 'Breakable'
breakable_parts => [qw( tires wheels windscreen )],
}
});
Obviously, this interface is better simplified as a method on C<Car>:
sub make_breakable {
my ( $self, %params ) = @_;
apply_all_roles($self, 'Breakable', { rebless_params => \%params });
}
my $car = Car->new();
$car->make_breakable( breakable_parts => [qw( tires wheels windscreen )] );
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,204 @@
# PODNAME: Moose::Manual::Support
# ABSTRACT: Policies regarding support, releases, and compatibility.
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Support - Policies regarding support, releases, and compatibility.
=head1 VERSION
version 2.2207
=head1 SUPPORT POLICY
There are two principles to Moose's policy of supported behavior.
=over 4
=item 1.
Moose favors correctness over everything.
=item 2.
Moose supports documented and tested behavior, not accidental behavior or side
effects.
=back
If a behavior has never been documented or tested, the behavior is
I<officially> undefined. Relying upon undocumented and untested behavior is
done at your own risk.
If a behavior is documented or tested but found to be incorrect later, the
behavior will go through a deprecation period. During the deprecation period,
use of that feature will cause a warning. Eventually, the deprecated feature
will be removed.
In some cases, it is not possible to deprecate a behavior. In this case, the
behavior will simply be changed in a major release.
=head1 RELEASE SCHEDULE
Moose is on a system of quarterly major releases, with minor releases as
needed between major releases. A minor release is defined as one that makes
every attempt to preserve backwards compatibility. Currently this means that we
did not introduce any new dependency conflicts, and that we did not make any
changes to documented or tested behavior (this typically means that minor
releases will not change any existing tests in the test suite, although they
can add new ones). A minor release can include new features and bug fixes.
Major releases may be backwards incompatible. Moose prioritizes
correctness over backwards compatibility or performance; see the L<DEPRECATION
POLICY> to understand how backwards incompatible changes are announced.
Major releases are scheduled to happen during fixed release windows. If the
window is missed, then there will not be a major release until the next
release window. The release windows are one month long, and occur during the
months of January, April, July, and October.
Before a major release, a series of development releases will be made so that
users can test the upcoming major release before it is distributed to CPAN. It
is in the best interests of everyone involved if these releases are tested as
widely as possible.
=head1 DEPRECATION POLICY
Moose has always prioritized correctness over performance and backwards
compatibility.
Major deprecations or API changes are documented in the Changes file as well
as in L<Moose::Manual::Delta>. The Moose developers will also make an effort
to warn users of upcoming deprecations and breakage through the Moose blog
(http://blog.moose.perl.org).
Deprecated APIs will be preserved for at least one year I<after the major
release which deprecates that API>. Deprecated APIs will only be removed in a
major release.
Moose will also warn during installation if the version of Moose being
installed will break an installed dependency. Unfortunately, due to the nature
of the Perl install process these warnings may be easy to miss.
=head1 BACKWARDS COMPATIBILITY
We try to ensure compatibility by having a extensive test suite (last count
over 18000 tests), as well as testing a number of packages (currently just
under 100 packages) that depend on Moose before any release.
The current list of downstream dependencies that are tested is in
C<xt/author/test-my-dependents.t>.
=head1 VERSION NUMBERS
Moose version numbers consist of three parts, in the form X.YYZZ. The X is the
"special magic number" that only gets changed for really big changes. Think of
this as being like the "5" in Perl 5.12.1.
The YY portion is the major version number. Moose uses even numbers for stable
releases, and odd numbers for trial releases. The ZZ is the minor version, and
it simply increases monotonically. It starts at "00" each time a new major
version is released.
Semantically, this means that any two releases which share a major version
should be API-compatible with each other. In other words, 2.0200, 2.0201, and
2.0274 are all API-compatible.
Prior to version 2.0, Moose version numbers were monotonically incrementing
two decimal values (0.01, 0.02, ... 1.11, 1.12, etc.).
Moose was declared production ready at version 0.18 (via L<<
http://www.perlmonks.org/?node_id=608144 >>).
=head1 PERL VERSION COMPATIBILITY
As of version 2.16, Moose will officially support being run on perl 5.10.1+. Our
current policy is to support the earliest version of Perl shipped in the latest
stable release of any major operating system (this tends to mean CentOS). We
will provide at least six months notice (two major releases) when we decide to
increase the officially supported Perl version.
"Officially supported" does not mean that these are the only versions of Perl
that Moose will work with. Our declared perl dependency will remain at 5.8.3
as long as our test suite continues to pass on 5.8.3. What this does mean is
that the core Moose dev team will not be spending any time fixing bugs on
versions that aren't officially supported, and new contributions will not be
rejected due to being incompatible with older versions of perl except in the
most trivial of cases. We will, however, still welcome patches to make Moose
compatible with earlier versions, if other people are still interested in
maintaining compatibility. As such, the current minimum required version of
5.8.3 will remain for as long as downstream users are happy to assist with
maintenance.
Note that although performance regressions are acceptable in order to maintain
backwards compatibility (as long as they only affect the older versions),
functionality changes and buggy behavior will not be. If it becomes impossible
to provide identical functionality between modern Perl versions and
unsupported Perl versions, we will increase our declared perl dependency
instead.
=head1 CONTRIBUTING
Moose has an open contribution policy. Anybody is welcome to submit a
patch. Please see L<Moose::Manual::Contributing> for more details.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

501
CPAN/Moose/Manual/Types.pod Normal file
View File

@@ -0,0 +1,501 @@
# PODNAME: Moose::Manual::Types
# ABSTRACT: Moose's type system
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Types - Moose's type system
=head1 VERSION
version 2.2207
=head1 TYPES IN PERL?
Moose provides its own type system for attributes. You can also use
these types to validate method parameters with the help of a MooseX
module.
Moose's type system is based on a combination of Perl 5's own
I<implicit> types and some Perl 6 concepts. You can create your
own subtypes with custom constraints, making it easy to express any
sort of validation.
Types have names, and you can re-use them by name, making it easy to
share types throughout a large application.
However, this is not a "real" type system. Moose does not magically make Perl
start associating types with variables. This is just an advanced parameter
checking system which allows you to associate a name with a constraint.
That said, it's still pretty damn useful, and we think it's one of the
things that makes Moose both fun and powerful. Taking advantage of the
type system makes it much easier to ensure that you are getting valid
data, and it also contributes greatly to code maintainability.
=head1 THE TYPES
The basic Moose type hierarchy looks like this
Any
Item
Bool
Maybe[`a]
Undef
Defined
Value
Str
Num
Int
ClassName
RoleName
Ref
ScalarRef[`a]
ArrayRef[`a]
HashRef[`a]
CodeRef
RegexpRef
GlobRef
FileHandle
Object
In practice, the only difference between C<Any> and C<Item> is
conceptual. C<Item> is used as the top-level type in the hierarchy.
The rest of these types correspond to existing Perl concepts.
In particular:
=over 4
=item
C<Bool> accepts C<1> for true, and undef, 0, or the empty string as false.
=item
C<Maybe[`a]> accepts either C<`a> or C<undef>.
=item
C<Num> accepts integers, floating point numbers (both in decimal notation &
exponential notation), 0, .0, 0.0 etc. It doesn't accept numbers with
whitespace, Inf, Infinity, "0 but true", NaN & other such strings.
=item
C<ClassName> and C<RoleName> accept strings that are either the name of a class or the name of a role. The class/role must already be loaded when the constraint is checked.
=item
C<FileHandle> accepts either an L<IO::Handle> object or a builtin perl filehandle (see L<Scalar::Util/openhandle>).
=item
C<Object> accepts any blessed reference.
=back
The types followed by "[`a]" can be parameterized. So instead of just
plain C<ArrayRef> we can say that we want C<ArrayRef[Int]> instead. We
can even do something like C<HashRef[ArrayRef[Str]]>.
The C<Maybe[`a]> type deserves a special mention. Used by itself, it
doesn't really mean anything (and is equivalent to C<Item>). When it
is parameterized, it means that the value is either C<undef> or the
parameterized type. So C<Maybe[Int]> means an integer or C<undef>.
For more details on the type hierarchy, see
L<Moose::Util::TypeConstraints>.
=head1 WHAT IS A TYPE?
It's important to realize that types are not classes (or
packages). Types are just objects (L<Moose::Meta::TypeConstraint>
objects, to be exact) with a name and a constraint. Moose maintains a
global type registry that lets it convert names like C<Num> into the
appropriate object.
However, class names I<can be> type names. When you define a new class
using Moose, it defines an associated type name behind the scenes:
package MyApp::User;
use Moose;
Now you can use C<'MyApp::User'> as a type name:
has creator => (
is => 'ro',
isa => 'MyApp::User',
);
However, for non-Moose classes there's no magic. You may have to
explicitly declare the class type. This is a bit muddled because Moose
assumes that any unknown type name passed as the C<isa> value for an
attribute is a class. So this works:
has 'birth_date' => (
is => 'ro',
isa => 'DateTime',
);
In general, when Moose is presented with an unknown name, it assumes
that the name is a class:
subtype 'ModernDateTime'
=> as 'DateTime'
=> where { $_->year() >= 1980 }
=> message { 'The date you provided is not modern enough' };
has 'valid_dates' => (
is => 'ro',
isa => 'ArrayRef[DateTime]',
);
Moose will assume that C<DateTime> is a class name in both of these
instances.
=head1 SUBTYPES
Moose uses subtypes in its built-in hierarchy. For example, C<Int> is
a child of C<Num>.
A subtype is defined in terms of a parent type and a constraint. Any
constraints defined by the parent(s) will be checked first, followed by
constraints defined by the subtype. A value must pass I<all> of these
checks to be valid for the subtype.
Typically, a subtype takes the parent's constraint and makes it more
specific.
A subtype can also define its own constraint failure message. This
lets you do things like have an error "The value you provided (20),
was not a valid rating, which must be a number from 1-10." This is
much friendlier than the default error, which just says that the value
failed a validation check for the type. The default error can, however,
be made more friendly by installing L<Devel::PartialDump> (version 0.14 or
higher), which Moose will use if possible to display the invalid value.
Here's a simple (and useful) subtype example:
subtype 'PositiveInt',
as 'Int',
where { $_ > 0 },
message { "The number you provided, $_, was not a positive number" };
Note that the sugar functions for working with types are all exported
by L<Moose::Util::TypeConstraints>.
=head1 TYPE NAMES
Type names are global throughout the current Perl
interpreter. Internally, Moose maps names to type objects via a
L<registry|Moose::Meta::TypeConstraint::Registry>.
If you have multiple apps or libraries all using Moose in the same
process, you could have problems with collisions. We recommend that
you prefix names with some sort of namespace indicator to prevent
these sorts of collisions.
For example, instead of calling a type "PositiveInt", call it
"MyApp::Type::PositiveInt" or "MyApp::Types::PositiveInt". We
recommend that you centralize all of these definitions in a single
package, C<MyApp::Types>, which can be loaded by other classes in your
application.
However, before you do this, you should look at the L<MooseX::Types>
module. This module makes it easy to create a "type library" module, which can
export your types as perl constants.
has 'counter' => (is => 'rw', isa => PositiveInt);
This lets you use a short name rather than needing to fully qualify the name
everywhere. It also allows you to easily create parameterized types:
has 'counts' => (is => 'ro', isa => HashRef[PositiveInt]);
This module will check your names at compile time, and is generally more
robust than the string type parsing for complex cases.
=head1 COERCION
A coercion lets you tell Moose to automatically convert one type to another.
subtype 'ArrayRefOfInts',
as 'ArrayRef[Int]';
coerce 'ArrayRefOfInts',
from 'Int',
via { [ $_ ] };
You'll note that we created a subtype rather than coercing C<ArrayRef[Int]>
directly. It's a bad idea to add coercions to the raw built in
types.
Coercions are global, just like type names, so a coercion applied to a built
in type is seen by all modules using Moose types. This is I<another> reason
why it is good to namespace your types.
Moose will I<never> try to coerce a value unless you explicitly ask for
it. This is done by setting the C<coerce> attribute option to a true value:
package Foo;
has 'sizes' => (
is => 'ro',
isa => 'ArrayRefOfInts',
coerce => 1,
);
Foo->new( sizes => 42 );
This code example will do the right thing, and the newly created
object will have C<[ 42 ]> as its C<sizes> attribute.
=head2 Deep coercion
Deep coercion is the coercion of type parameters for parameterized
types. Let's take these types as an example:
subtype 'HexNum',
as 'Str',
where { /[a-f0-9]/i };
coerce 'Int',
from 'HexNum',
via { hex $_ };
has 'sizes' => (
is => 'ro',
isa => 'ArrayRef[Int]',
coerce => 1,
);
If we try passing an array reference of hex numbers for the C<sizes>
attribute, Moose will not do any coercion.
However, you can define a set of subtypes to enable coercion between
two parameterized types.
subtype 'ArrayRefOfHexNums',
as 'ArrayRef[HexNum]';
subtype 'ArrayRefOfInts',
as 'ArrayRef[Int]';
coerce 'ArrayRefOfInts',
from 'ArrayRefOfHexNums',
via { [ map { hex } @{$_} ] };
Foo->new( sizes => [ 'a1', 'ff', '22' ] );
Now Moose will coerce the hex numbers to integers.
Moose does not attempt to chain coercions, so it will not
coerce a single hex number. To do that, we need to define a separate
coercion:
coerce 'ArrayRefOfInts',
from 'HexNum',
via { [ hex $_ ] };
Yes, this can all get verbose, but coercion is tricky magic, and we
think it's best to make it explicit.
=head1 TYPE UNIONS
Moose allows you to say that an attribute can be of two or more
disparate types. For example, we might allow an C<Object> or
C<FileHandle>:
has 'output' => (
is => 'rw',
isa => 'Object | FileHandle',
);
Moose actually parses that string and recognizes that you are creating
a type union. The C<output> attribute will accept any sort of object,
as well as an unblessed file handle. It is up to you to do the right
thing for each of them in your code.
Whenever you use a type union, you should consider whether or not
coercion might be a better answer.
For our example above, we might want to be more specific, and insist
that output be an object with a C<print> method:
duck_type 'CanPrint', [qw(print)];
We can coerce file handles to an object that satisfies this condition
with a simple wrapper class:
package FHWrapper;
use Moose;
has 'handle' => (
is => 'rw',
isa => 'FileHandle',
);
sub print {
my $self = shift;
my $fh = $self->handle();
print {$fh} @_;
}
Now we can define a coercion from C<FileHandle> to our wrapper class:
coerce 'CanPrint'
=> from 'FileHandle'
=> via { FHWrapper->new( handle => $_ ) };
has 'output' => (
is => 'rw',
isa => 'CanPrint',
coerce => 1,
);
This pattern of using a coercion instead of a type union will help
make your class internals simpler.
=head1 TYPE CREATION HELPERS
The L<Moose::Util::TypeConstraints> module exports a number of helper
functions for creating specific kinds of types. These include
C<class_type>, C<role_type>, C<maybe_type>, and C<duck_type>. See the
docs for details.
One helper worth noting is C<enum>, which allows you to create a
subtype of C<Str> that only allows the specified values:
enum 'RGB', [qw( red green blue )];
This creates a type named C<RGB>.
=head1 ANONYMOUS TYPES
All of the type creation functions return a type object. This type
object can be used wherever you would use a type name, as a parent
type, or as the value for an attribute's C<isa> option:
has 'size' => (
is => 'ro',
isa => subtype( 'Int' => where { $_ > 0 } ),
);
This is handy when you want to create a one-off type and don't want to
"pollute" the global namespace registry.
=head1 VALIDATING METHOD PARAMETERS
Moose does not provide any means of validating method
parameters. However, there are several MooseX extensions on CPAN which
let you do this.
The simplest and least sugary is L<Params::ValidationCompiler>. This
lets you validate a set of named parameters using Moose types:
use Moose::Util::TypeConstraints qw( find_type_constraint );
use Params::ValidationCompiler qw( validation_for );
{
my $validator = validation_for(
params => {
foo => { type => find_type_constraint('Int') },
bar => {
type => find_type_constraint('Str'),
optional => 1,
},
baz => {
type => find_type_constraint('Int'),
default => 42,
},
},
);
sub foo {
my %args = $validator->(@_);
}
}
L<Params::ValidationCompiler> also supports coercions.
There are several more powerful extensions that support method parameter
validation using Moose types, including L<Moops>, which gives you a full-blown
C<method> keyword.
method morning ( Str $name ) {
$self->say("Good morning ${name}!");
}
=head1 LOAD ORDER ISSUES
Because Moose types are defined at runtime, you may run into load
order problems. In particular, you may want to use a class's type
constraint before that type has been defined.
In order to ameliorate this problem, we recommend defining I<all> of your
custom types in one module, C<MyApp::Types>, and then loading this module in
all of your other modules.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,386 @@
# PODNAME: Moose::Manual::Unsweetened
# ABSTRACT: Moose idioms in plain old Perl 5 without the sugar
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Manual::Unsweetened - Moose idioms in plain old Perl 5 without the sugar
=head1 VERSION
version 2.2207
=head1 DESCRIPTION
If you're trying to figure out just what the heck Moose does, and how
it saves you time, you might find it helpful to see what Moose is
I<really> doing for you. This document shows you the translation from
Moose sugar back to plain old Perl 5.
=head1 CLASSES AND ATTRIBUTES
First, we define two very small classes the Moose way.
package Person;
use DateTime;
use DateTime::Format::Natural;
use Moose;
use Moose::Util::TypeConstraints;
has name => (
is => 'rw',
isa => 'Str',
required => 1,
);
# Moose doesn't know about non-Moose-based classes.
class_type 'DateTime';
my $en_parser = DateTime::Format::Natural->new(
lang => 'en',
time_zone => 'UTC',
);
coerce 'DateTime'
=> from 'Str'
=> via { $en_parser->parse_datetime($_) };
has birth_date => (
is => 'rw',
isa => 'DateTime',
coerce => 1,
handles => { birth_year => 'year' },
);
enum 'ShirtSize' => [qw( s m l xl xxl )];
has shirt_size => (
is => 'rw',
isa => 'ShirtSize',
default => 'l',
);
This is a fairly simple class with three attributes. We also define an enum
type to validate t-shirt sizes because we don't want to end up with something
like "blue" for the shirt size!
package User;
use Email::Valid;
use Moose;
use Moose::Util::TypeConstraints;
extends 'Person';
subtype 'Email'
=> as 'Str'
=> where { Email::Valid->address($_) }
=> message { "$_ is not a valid email address" };
has email_address => (
is => 'rw',
isa => 'Email',
required => 1,
);
This class subclasses Person to add a single attribute, email address.
Now we will show what these classes would look like in plain old Perl
5. For the sake of argument, we won't use any base classes or any
helpers like C<Class::Accessor>.
package Person;
use strict;
use warnings;
use Carp qw( confess );
use DateTime;
use DateTime::Format::Natural;
sub new {
my $class = shift;
my %p = ref $_[0] ? %{ $_[0] } : @_;
exists $p{name}
or confess 'name is a required attribute';
$class->_validate_name( $p{name} );
exists $p{birth_date}
or confess 'birth_date is a required attribute';
$p{birth_date} = $class->_coerce_birth_date( $p{birth_date} );
$class->_validate_birth_date( $p{birth_date} );
$p{shirt_size} = 'l'
unless exists $p{shirt_size};
$class->_validate_shirt_size( $p{shirt_size} );
return bless \%p, $class;
}
sub _validate_name {
shift;
my $name = shift;
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
defined $name
or confess 'name must be a string';
}
{
my $en_parser = DateTime::Format::Natural->new(
lang => 'en',
time_zone => 'UTC',
);
sub _coerce_birth_date {
shift;
my $date = shift;
return $date unless defined $date && ! ref $date;
my $dt = $en_parser->parse_datetime($date);
return $dt ? $dt : undef;
}
}
sub _validate_birth_date {
shift;
my $birth_date = shift;
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
$birth_date->isa('DateTime')
or confess 'birth_date must be a DateTime object';
}
sub _validate_shirt_size {
shift;
my $shirt_size = shift;
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
defined $shirt_size
or confess 'shirt_size cannot be undef';
my %sizes = map { $_ => 1 } qw( s m l xl xxl );
$sizes{$shirt_size}
or confess "$shirt_size is not a valid shirt size (s, m, l, xl, xxl)";
}
sub name {
my $self = shift;
if (@_) {
$self->_validate_name( $_[0] );
$self->{name} = $_[0];
}
return $self->{name};
}
sub birth_date {
my $self = shift;
if (@_) {
my $date = $self->_coerce_birth_date( $_[0] );
$self->_validate_birth_date( $date );
$self->{birth_date} = $date;
}
return $self->{birth_date};
}
sub birth_year {
my $self = shift;
return $self->birth_date->year;
}
sub shirt_size {
my $self = shift;
if (@_) {
$self->_validate_shirt_size( $_[0] );
$self->{shirt_size} = $_[0];
}
return $self->{shirt_size};
}
Wow, that was a mouthful! One thing to note is just how much space the
data validation code consumes. As a result, it's pretty common for
Perl 5 programmers to just not bother. Unfortunately, not validating
arguments leads to surprises down the line ("why is birth_date an
email address?").
Also, did you spot the (intentional) bug?
It's in the C<_validate_birth_date()> method. We should check that
the value in C<$birth_date> is actually defined and an object before
we go and call C<isa()> on it! Leaving out those checks means our data
validation code could actually cause our program to die. Oops.
Note that if we add a superclass to Person we'll have to change the
constructor to account for that.
(As an aside, getting all the little details of what Moose does for
you just right in this example was really not easy, which emphasizes
the point of the example. Moose saves you a lot of work!)
Now let's see User:
package User;
use strict;
use warnings;
use Carp qw( confess );
use Email::Valid;
use Scalar::Util qw( blessed );
use parent 'Person';
sub new {
my $class = shift;
my %p = ref $_[0] ? %{ $_[0] } : @_;
exists $p{email_address}
or confess 'email_address is a required attribute';
$class->_validate_email_address( $p{email_address} );
my $self = $class->SUPER::new(%p);
$self->{email_address} = $p{email_address};
return $self;
}
sub _validate_email_address {
shift;
my $email_address = shift;
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
defined $email_address
or confess 'email_address must be a string';
Email::Valid->address($email_address)
or confess "$email_address is not a valid email address";
}
sub email_address {
my $self = shift;
if (@_) {
$self->_validate_email_address( $_[0] );
$self->{email_address} = $_[0];
}
return $self->{email_address};
}
That one was shorter, but it only has one attribute.
Between the two classes, we have a whole lot of code that doesn't do
much. We could probably simplify this by defining some sort of
"attribute and validation" hash, like this:
package Person;
my %Attr = (
name => {
required => 1,
validate => sub { defined $_ },
},
birth_date => {
required => 1,
validate => sub { blessed $_ && $_->isa('DateTime') },
},
shirt_size => {
required => 1,
validate => sub { defined $_ && $_ =~ /^(?:s|m|l|xl|xxl)$/i },
}
);
Then we could define a base class that would accept such a definition
and do the right thing. Keep that sort of thing up and we're well on
our way to writing a half-assed version of Moose!
Of course, there are CPAN modules that do some of what Moose does,
like C<Class::Accessor>, C<Class::Meta>, and so on. But none of them
put together all of Moose's features along with a layer of declarative
sugar, nor are these other modules designed for extensibility in the
same way as Moose. With Moose, it's easy to write a MooseX module to
replace or extend a piece of built-in functionality.
Moose is a complete OO package in and of itself, and is part of a rich
ecosystem of extensions. It also has an enthusiastic community of
users and is being actively maintained and developed.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut