Cees Hek wrote:
> Since the list has been quiet for the last little while, I thought I
> would stir things up a bit. There was a thread about Class::Trait
> recently on perlmonks that caught my attention:
>
> http://perlmonks.org/?node_id=509958
>
> I had looked at Traits before, but never found the time to look into
> them carefully. The reason I think they are interesting, is that
> Traits aim to solve a lot of the problems with both Multiple
> Inheritance and Mixins. And since the plugin system in
> CGI::Application is based around a mixin architecture, I think it is
> worth a look.
>
> In CGI::Application, we don't really have a plugin interface. We have
> conventions and best practices that tell developers to just use
> Exporter to export methods into the caller class (ie a very simple
> mixin strategy).
>
> But mixins have some problems and dangers associated with them. The
> biggest one being method name colisions. What happens if a plugin
> tries to export a method that already exists in the caller class? It
> probably clobers it in most instances, depending on how the plugin
> author implemented their code.
How does Class::Trait handle 2 plugins trying to export the same method?
> Traits are not really much more than mixins with a lot of extra checks
> and balances for namespace collisions, and ways to overcome those
> problems when they arise. First of all, a Trait will never overwrite
> an existing method in the caller. What it will do is allow you to
> alias the trait method with a new name, so that you can still use the
> method provided by the trait without it conflicting with your existing
> code.
What if you want your plugin to override an existing method? For
instance, CAP::AnyTemplate overrides load_tmpl(), CAP::TT overrides,
load_tmpl(), CAP::Apache overrides query(), etc.
Would we then have to have a mix of Class::Trait and Exporter?
> For example lets take the LogDispatch plugin. It exports a 'log'
> method into the caller namespace. Lets say you already have a 'log'
> method in there that you do not want to get rid of. When you load the
> LogDispatch Trait, you can tell it that you want the 'log' method, but
> you want to call it 'get_logger' instead. Class::Trait will
> automatically export a 'get_logger' method that is aliased to the
> original 'log' method in the Trait.
>
>
> Another nice benefit of Traits is that you can specify method
> requirements in a Trait. So if I implemented the Session plugin using
> traits, and I put in a requirement that the Session trait requires a
> 'dbh' method to be available, then the Class:Trait module would make
> sure that a 'dbh' is available and provide an error if it can not find
> a dbh method (either in the caller class, or in another Trait that is
> also being loaded).
This is nice. But is there a way to do this now? Can't you write your
own export() method to check for the availability of a method. This may
get kinda tricky if the method is added later, or not completely visible
to export(). But this would still be done at compile time.
> Class::Trait will add a slight bit of extra processing to the module
> at startup, since it is doing more work than a straight Exporter style
> mixin, but all of this work is done at compile time. All of the
> exported methods are still flattened into the caller's namespace, so
> there is absolutely no extra runtime penalty.
>
> Loading plugins will also look slightly different, since they are
> loaded through the Class::Trait module instead of being 'use'd
> directly:
>
> use Class::Trait qw(CGI::Application::Plugin::Session);
>
> We could create a simple wrapper that simplifies that to something like this:
>
> use CGI::Application::Plugin qw(Session);
>
> - or with some extra options -
>
> use CGI::Application::Plugin
> 'LogDispatch' => {
> alias => { log => 'get_logger' },
> },
> 'Session'
> );
Whether or not we use traits, I think having a more uniform way to 'use'
plugins is a good idea.
> I think it might be useful at some point in the future to look at
> using Traits instead of straight exporter style mixins to implement
> the plugin system we use today. It would add extra safeguards and
> checks into the plugin system that would make it more robust, and it
> adds a clean conflict resolution mechanism in case of method name
> conflicts.
All of these things sound good, I just want to make sure that plugins
can still do tricky stuff if they want to.
--
Michael Peters
Developer
Plus Three, LP
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/[email protected]/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]