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

