|WWW::Mechanize::Sleepy - pauses between requests|
|WWW::Mechanize::Cached - caches requests|
|WWW::Mechanize::Timed - times requests|
This approach isnt viable in the long term because the number of possible
combinations of behavior grows too fast. So how can we address this problem?
A partial solution comes from Module::Pluggable. This module allows
you to create plugins - specially-named packages, installed just like
regular modules. A base package, which uses Module::Pluggable, can
then automatically search for and load extra functions via these
This solves the problem of extending a base class - if youre the one
who controls the base classs source code.
CWWWW::Mechanize::Pluggable - plugins with a twist
The simplest way to solve the problem is just to create a subclass of
the class you want to add plugin functionality to - in our case,
WWW::Mechanize - and then write plugins. And as long as all youre
doing is just adding new functions, youre in good shape.
But what if you want to change the way something functions, rather than just add something new? You have a problem, because a plugin cant do that - or rather, two different plugins that want to alter the same base-class method cant do so without knowing about each other. This might seem like a good-enough solution, but it has the same problem as the subclass the subclasses approach: you have a combinatorial explosion of checks that have to be made every time a new module that wants to alter the same base-class method gets into the act.
The approach used in WWW::Mechanize::Pluggable is to combine the proxy pattern (one class intercepts all the calls for another and then passes them on) and the decorator pattern (one class instantiates another, then exposes methods matching all of the second classes methods, with its own code inserted before and/or after the calls to the contained class).
Perl provides us with very flexible ways to deal with this process.
We use AUTOLOAD to catch all the calls to the class. We actually implement very little in WWW::Mechanize::Pluggable; only enough to be able to create the base object and its contained WWW::Mechanize object.
To decorate, we add a hash of pre-hook and post-hook lists. These are subroutines to be called before (pre-hook) and after (post-hook) the base-class methods. Now its possible to alter either the behavior of a given method, or to feed it different parameters behind the back of the main program.
Well speak specifically about WWW::Mechanize::Pluggable here; wo hope to extract the pluggability into a completely separate module in the very near future, allowing the creation of ::Pluggable versions of any module you please.
|perl v5.20.3||WWW::MECHANIZE::PLUGGABLE::DESIGN (3)||2011-07-02|