document shortcomings with inner/augment and MI.
[gitmo/Moose.git] / lib / Moose / Manual / MethodModifiers.pod
index c60837c..15bb438 100644 (file)
@@ -1,13 +1,15 @@
-=pod
+package Moose::Manual::MethodModifiers;
+
+# ABSTRACT: Moose's method modifiers
 
-=head1 NAME
+__END__
 
-Moose::Manual::Attribute - Moose's Method Modifiers
+=pod
 
 =head1 WHAT IS A METHOD MODIFIER?
 
-Moose provides a feature called "method modifiers". Another word for
-this feature might be "hooks" or "advice".
+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:
 
@@ -16,7 +18,7 @@ It's probably easiest to understand this feature with a few examples:
   use Moose;
 
   sub foo {
-      print "foo\n";
+      print "    foo\n";
   }
 
   before 'foo' => sub { print "about to call foo\n"; };
@@ -26,19 +28,19 @@ It's probably easiest to understand this feature with a few examples:
       my $orig = shift;
       my $self = shift;
 
-      print "I'm around foo\n";
+      print "  I'm around foo\n";
 
       $self->$orig(@_);
 
-      print "I'm still around foo\n";
+      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
+    I'm around foo
+      foo
+    I'm still around foo
   just called foo
 
 You probably could have figured that out from the names "before",
@@ -63,18 +65,22 @@ modifiers run from first added to last:
 
 =head1 WHY USE THEM?
 
-Method modifiers have many uses. One very common use is in roles. This
-lets roles alter the behavior of methods in the classes that use
-them. See L<Moose::Manual::Roles> for more about roles.
+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.
 
-Modifiers really are at their most useful in roles, so 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 usages.
+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 also be used to add behavior to a method that
-Moose generates for you, such as an attribute accessor:
+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' );
 
@@ -87,7 +93,7 @@ Moose generates for you, such as an attribute accessor:
   };
 
 Another use for the before modifier would be to do some sort of
-pre-checking on a method call. For example:
+prechecking on a method call. For example:
 
   before 'size' => sub {
       my $self = shift;
@@ -96,8 +102,9 @@ pre-checking on a method call. For example:
           if @_ && $self->is_growing;
   };
 
-This lets us implement logical checks that don't fit well into
-constraints.
+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.
@@ -105,12 +112,13 @@ was taken.
 Note that the return values of both before and after modifiers are
 ignored.
 
-An around modifier is a bit more powerful than either a before or
-after modifier. First, it is easy to modify the arguments being passed
-onto the original method in an around modifier. Second, you can decide
-to simply not call the original method at all, unlike with other
-modifiers. Finally, you can modify the return value with an around
-modifier.
+=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.
@@ -129,6 +137,50 @@ I<then> the object, and finally any arguments passed to the method.
       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.
+
+
 =head1 INNER AND AUGMENT
 
 Augment and inner are two halves of the same feature. The augment
@@ -166,9 +218,9 @@ implementation:
   augment 'as_xml' => sub {
       my $self = shift;
 
-      my $xml = "<report>\n";
+      my $xml = "  <report>\n";
       $xml .= inner();
-      $xml .= "</report>\n";
+      $xml .= "  </report>\n";
 
       return $xml;
   };
@@ -176,8 +228,8 @@ implementation:
 When we call C<as_xml> on a Report object, we get something like this:
 
   <document>
-  <report>
-  </report>
+    <report>
+    </report>
   </document>
 
 But we also called C<inner()> in C<Report>, so we can continue
@@ -192,9 +244,9 @@ subclassing and adding more content inside the document:
   augment 'as_xml' => sub {
       my $self = shift;
 
-      my $xml = '<income>' . $self->income . '</income>';
+      my $xml = '    <income>' . $self->income . '</income>';
       $xml .= "\n";
-      my $xml = '<expenses>' . $self->expenses . '</expenses>';
+      $xml .= '    <expenses>' . $self->expenses . '</expenses>';
       $xml .= "\n";
 
       $xml .= inner() || q{};
@@ -205,21 +257,28 @@ subclassing and adding more content inside the document:
 Now our report has some content:
 
   <document>
-  <report>
-  <income>$10</income>
-  <expenses>$8</expenses>
-  </report>
+    <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 I<parent
-(least specific) to child (most specific). This inverts the normal
-order, where the child's method is called first, and it in turn will
-call C<< $self->SUPER::method >> to call the parent.
+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.
+
+=head2 CAVEATS
+
+Inner/augment does not work well with multiple inheritance (that is, a
+sub augmenting one defined in more than one parent), due to how C<inner()>
+looks for implementations in parent classes.
 
-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.
 
 =head1 OVERRIDE AND SUPER
 
@@ -257,17 +316,4 @@ semi-colon:
 
   after 'foo' => sub { };
 
-=head1 AUTHOR
-
-Dave Rolsky E<lt>autarch@urth.orgE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2008 by Infinity Interactive, Inc.
-
-L<http://www.iinteractive.com>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
 =cut