Subroutine attributes: where and how to use them
I watched this video about Subroutine attributes, and I wrote myself a summary of what I learned. I thought I could share it.
A subroutine attribute can be used just like an around() modifier: it can modify a what a subroutine does, or add some behavior each time the subroutine is called. The main difference with around() is that it's indicated by an attribute next to the subroutine name, and it can take parameters. Like this:
sub some_subroutine :Some_attribute('some', 'parameters', $var) { ... }
sub other_subroutine :Some_attribute('other', 'values', $var2) { ... }
At 18:00 you will find an example of how to use a subroutine attribute like an around() modifier, by using Attribute::Handler and rewriting the subroutine inside of the attribute definition.
The same thing can also be done with Sub::Attribute. It gives access to less context in the modifier, but its documentation is much simpler to read, and it avoids one danger of In the end, the declaration of the attribute function will be very similar whichever module you use. Edit: Reini's tells us in a comment about the dangers of Attribute::Handler, and of the approach presented in the video for using Sub::Attribute.
I have found MooseX::ModifyTaggedMethods as yet another alternative. It uses the before(), after() and around() modifiers, to modify the behavior of the subroutines tagged with a given subroutine attribute. It is a simpler syntax to do this kind of job. But I'm not sure how it does what it does, and I didn't check whether it enables to pass arguments to the attribute function.
Subroutine attributes can be used to do:
complex logging (mark for each subroutine how it should be logged)
authorization system (tell who can use which subroutines). There is an example here
counting how many times a given type of tasks was done
wrapping methods in database transactions; for example to roll back after each test, to leave the database in its initial state
And some additional ideas:
To indicate subroutines to Memoize (see Attribute::Memoize)
To debug
Let me know if there are other uses, and I will add them to this list.
Addendum to the video: I have written this other blog post, comparing Subroutine attributes with Method modifiers and Aspects: three different ways to introduce orthogonal concerns, suited for different needs. Check it out.
PS: Read Reini's comment for warnings about the dangers
I've added this to the Google+ post of the video:
I'm missing the important distinction and dangers of Attribute::Handlers vs Sub::Attributes.
Attribute::Handlers evaluates all code attribute arguments, Sub::Attributes not.
sub cleanup :Help(unlink some files) {}
Will not only attach the help string to the sub, it will delete some files. So never leave the first arg unquoted!
His eval example for Sub::Attributes is also pretty dangerous, as it merely uses the same dirty and insecure trick Damian Conway used, without any security checks.
Cheers Reini.
I added a note pointing to your comment, in the paragraph about Sub::Attribute.