One thing I think you should note in your documentation is that it's very important to realize that a software must not rely on aspects to function. That is to say, if all pointcuts fail to match, the software must still be correct. Aspects should generally add behaviour, not alter it.
For example, one common example Java programmers use is to mark code as thread-safe. However, if a pointcut fails to match a function which must be thread-safe, the match fails silently. As a result, previously thread-safe code may no longer be thread-safe, but the programmer won't notice this and the tests are highly likely to not catch this.
So if your pointcuts match all methods named foo_\w+ and some bright programmer fails to notice this action at a distance (and who would fail to notice action at a distance?) and renames some functions that the pointcuts previously matches, the behaviour of the code is altered, but it's awfully hard to notice this.
This is one of the reasons I like roles. Consider this:
package Role::Munge;
use Moose::Role;
requires qw(some_method);
before 'another_method' => sub {
my $self = shift;
my $stuff = $self->some_method;
# do more stuff
};
If some enterprising programmer renamed either 'some_method' or 'another_method', this code fails at composition time and gives composition safety. AOP silent-failure modes and action at a distance were one of the reasons roles (traits) were created in the first place.
So if you find AOP useful, that's great. Just note that if your system is incorrect without aspects, you have a major design flaw.
Read More