On 11/21/05, Michael Peters <[EMAIL PROTECTED]> wrote:
>
> > 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?
Good question. Since I am still in the 'this is worth investigating
stage', I don't have all the answers. My guess is that either one of
the methods is chosen, and a warning is displayed about the
duplication, or a compiler error is throw and the user is asked to
resolve the dependancy. One way to resolve the conflict is to tell
one of the Traits to not export one of it's methods. The docs give an
example of this:
use Class::Trait
'TComparable' => {
# exclude the basic equality method
# from TComparable and use the ones
# in TEquality instead.
exclude => [ "notEqualTo", "equalTo" ]
},
'TEquality' # <- use equalTo and notEqualTo from here
);
> > 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?
Another good question. First, to clarify your examples, CAP::TT does
not override load_tmpl, it just calls the load_tmpl hook in case the
user has registered any load_tmpl callbacks. I believe that
CAP::AnyTemplate works the same way (but don't quote me on that).
As for CAP::Apache, perhaps this module fits better as a subclass
instead of as a mixin. CAP::Apache is not necesarily adding new
unrelated functionality into CGI::Application. It is extending
existing functionality of CGI::Application.
However, I would think that the existing Exporter system would
continue to function even if some of the new plugins used a
Class::Trait system instead.
As for a workable (although not ideal) solution, Class::Trait only
fails to override methods that actually exist directly in the callers
namespace. Since CAP::Apache overrider methods that exist in the
CGI::Application namespace, Class::Trait would still export all the
methods, since the methods don't exist directly in the callers
namespace (they exist in a super class).
All I have really done here is stated that the examples you gave
probably won't cause any issues with Class::Trait, however that
doesn't mean that there isn't another example where it might still
cause problems.
> > 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.
Sure, but would you expect every plugin author to write their own
export method? I am just suggesting a central plugin structure that
takes care of all this for you (whether it is Class::Trait, or
something like it that we hack up ourselves)
> > 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.
Agreed. I think it would clarify the code quite a bit, and in most
instances save typing as well.
> > 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.
You've brought up some qood questions, and I am sure there will be
more. I think a good aim for us it to make a plugin system that
doesn't have to be tricky to let us do all the things that need to be
done (both for the plugin users and developers).
Cheers,
Cees
---------------------------------------------------------------------
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]