On 1/17/07, Ronald J Kimball <[EMAIL PROTECTED]> wrote:
>
> 22 people came to last night's tech meeting.
>
> Guillermo Roditi got partway through a brief presentation of his new
> MooseX::Object::Pluggable module, but he was cut short by the building's
> alarm system going off, and we all had to evacuate!  You can find
> Guillermo's module, which uses Moose roles to implement plugins, on CPAN.
>

And if you are feeling masochistic I will be playing with black magic in new
branches shortly at:
http://code2.0beta.co.uk/moose/svn

In case any of you were interested I will finish my presentation here.

While everything I do here could be easily done with Multiple Inheritance, a
long line or Single Inheritance, or runtime @ISA magic I wanted to take a
horizontal, rather than vertical approach to  adding plugin functionality.
Why horizontal? Because vertical gets messy and because I wanted to do
something different.

PS Yes, you could also do it by moving around closures in the symbol table,
but you'd really have to hate yourself.

Basics:
When your class is loaded C<with 'MooseX::Object::Pluggable'> as soon as the
first plugin is loaded an anonymous class, which inherits form your current
class will be created. Immediately afterwards your current instance ($self)
will be re blessed into an instance of the anonymous class we just created.

This anon class, which is guaranteed to have a single instance as long as
you don't do anything remarkably stupid, will be the consuming class for all
roles (plugins). This approach allows us to dynamically alter our  initial
object's behavior  while  keeping other instances intact. Instance-based
behavior allows us to create multiple instances of the same object and alter
them dynamically at runtime without them affecting each other (altering @ISA
would have created class-wide modifications)

This is what I meant by horizontal expansion. Time for a map.

$self --ISA--> AnonClass --ISA--> YourApp
                       |-->RoleA
                       |-->RoleB

How Roles are applied (anon wrapping, MI ISA hackery, symbol table black
magic ) is up to Moose.

Plugins:
Plugins are runtime roles where the only huge limitation is the lack of
C<override> (It works, but not as expected. Stop thinking veritcally!!!!! we
are horizontal) Plugins may override functionality in the consuming class
via C<around, before, after>. Plugins like inside special name spaces as
well. Typically YourApp::Plugin::*


Extensions:
All plugins, upon loading, will search for extensions. Extensions are  a
sort of subplugin that will automatically be loaded if another plugin is
loaded. This allows plugins to alter the behavior of other, previously
loaded plugins. If this sounds a little crazy, it is, but it allows me to do
fun things.

eg
the following exist
Plugin::Foo
Plugin::Bar
Plugin::Bar::ExtensionFor::Foo;

If Bar is loaded after Foo, then Bar::ExtensionFor::Foo will also be loaded
and allowed to override Foo.


Efficiency:
No, thanks. You are using Moose, runtime loading of objects and runtime
instantiation of anon classes. You were doomed way before I came in.

Sugar:
It will totally give you cavities.

Problems
The anon class hijack is done lazily upon first plugin load. if a plugin is
never loaded your ISA will never be hijacked leading to unpredictable
results from  $self->blessed and ref $self. It can be fixed (there's a
branch already) by overriding BUILD to hijack upon creation, BUT then you
_need_ BUILD to exist in your original app. Thats not so sugary. Work to
jijack BUILD automagically is in progress.

Questions?
Criticism?

No??? [looks around]

Ok thanks everyone!


Guillermo
http://search.cpan.org/~groditi/ <http://search.cpan.org/%7Egroditi/>
 
_______________________________________________
Boston-pm mailing list
[email protected]
http://mail.pm.org/mailman/listinfo/boston-pm

Reply via email to