Bill Catlan wrote:
I think the simplest solution for plugins to work
like C::A::ValidateRM
does. I don't think the proposed base class really


Mark-

I think I prefer your suggestion of using the standard
export technique - although I still firmly believe
that separate namespaces are essential.

However, I'm unclear on how Exporter works in an
object oriented context.  How does check_rm get into
the $self object below?

From CGI::Application::ValidateRM:

sub form_process {
my $self = shift;
use CGI::Application::ValidateRM;
my ($results, $err_page) =
$self->check_rm('form_display','_form_profile');
return $err_page if $err_page; ...
}


Here is a restatement of our requirements from earlier
discussion:
1) a separate name space for each plugin
2) plugins must be able to discover and use other
plugins
3) allow object caching by plugins

1) I'm now leaning in the direction of not needing a separate namespace for each plugin as long as each plugin will have a store in the application object. This would be solved by the suggestion that a plugin for incorporating 'Foo::Bar' would use $self->{'Foo::Bar'}.

Maybe if you could think of a case where separate namespaces for
plugins would be essential it would help.

Also, if we use Mark's idea of simply using Exporter then the user
can still turn off methods he doesn't want to use, just like with
any other module using Exporter. So if you override 'load_tmpl' in
you plugin but the user doesn't want it to override his method, but
still wants to use other methods that your plugin provides, it's
very easy to do.

2) If we follow the naming convention repeated above, this would
solve it. If an auth plugin wanted to access a 'Session' plugin,
then he could use $self->{'Session'} or $self->session.

3) Once again, this is solved by the above.

I think the solution I'm going to try implementing
looks like this:

In C::A::MyApp or C::A::AppBase:

use C::A::Plugin::MyPlugin( name => myname, exported
=> 0|1 );

Here, name attribute (UID) is optional, and a
universally unique name (UID) will be provided by
default.

Here's what will happen:

$self is a C::A object or child thereof.

$self->{_plugins}{UID}{ ref => $plugin_object,
exported => 0|1 ...}

Where exported equals 1, exported methods will be
available as follows:

$self->pub_method;
Plugins can discover each other by looking at all
plugins on $self->{_plugins} and check their ref
types.


Singleton plugins will be responsible for makeing
themselves singletons.

Plugin authors will inherit from base class
C::A::Plugin which will provide exporting functions
and a DESTROY method that will keep $self->{_plugins}
synchronized with plugin object destruction. If this
synchronizing method is problematic, the 'ref' hash
key above might be replaced with a 'idtag' (random ID
number) and 'type' (C::A::Plugin::MyPlugin) attributes
which will be deleted when the associated plugin
object is destroyed. (I've heard of linking these
kinds of things with tie, but I don't want to use
tie.)

Just seems too complicated for such a simple issue. But maybe that's just me.

helps this. It just
does the exporting in a different way. It uses
attributes to do this,
which are less well known than the standard EXPORT
method.

I don't think it's too much of ask of plugin writers
to use standard
Exporter techniques-- export public routines and
hide private ones.

I'm starting to agree with Mark here.

I propose the following alternate solution.

1. Rename and refactor existing plugin modules to be
consistent:
  - ::Session
  - ::ValidateRM
  - ::Config::Simple
  - ::TT


Sounds good.

Thoughts?

I still think we should put 'Plugin' in the object's name. There are many modules out there that split their work up into several classes that are a part of the same distribution. All of these helper classes exist under the same namespace as the original (Class::DBI has Class::DBI::Column, Class::DBI::Iterator, Class::DBI::Relationship, etc and TT does the same thing).

I think it might be misleading to have these plugin directly under
the CGI::Application namespace since they aren't used by C::A but by
the user. By putting them in a Plugin namespace then there is no
confusion. This is also what Class::DBI and TT do and they are very
successful in attracting users.

>>2. Simply update the POD of CGI::Application to
explain what's going on,
both for users and writers of plugins. Something
like this:

=head1 PLUG-INS

CGI::Application has a plug-in architecture that is
easy to use and easy
to develop new plug-ins for.

=head2 Existing plug-ins

Here are some plug-ins that have already been
developed for
CGI::Application. For a current complete list,
please consult CPAN:



http://search.cpan.org/search?query=Class%3A%3ADBI%3A%3APlugin&mode=module

=over 4

=item *

L<CGI::Application::Plugin::Session> - Integration
with L<CGI::Session>

=item *

L<CGI:::Application::Plugin::ValidateRM> -
Integration with Data::FormValidator and
HTML::FillInForm

=item *

L<CGI::Application::ValidateRM::TT> - Use
L<Template::Toolkit> as an alternative to
HTML::Template.

=item *

L<CGI::Application::Plugin::Config::Simple> -
Integration with Config::Simple.

=back

Consult each plug-in for the exact usage syntax.


=head2 Writing Plug-ins

Writing plug-ins is simple. Simply create a new
package, and export the
methods that you want to become part of a
CGI::Application project. See
L<CGI::Application::Plugin::ValidateRM> for an
example.

You only need to keep in mind that your extension
should "play well with
others". The method names exported should be unique.
Also, additions to
the CGI::Application object should be designed not
to conflict with other
potentional plug-ins. For that reason, it's
recommended that you add a
a hash key to the CGI::Application which reflects
the name of your
plug-in, such as:

$self->{'Config::Simple'}

###########

Thoughts?

The above pod would work for me except for a blurb about naming your plugin in the C::A::Plugin namespace :)

--
Michael Peters
Developer
Plus Three, LP



--
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]



Reply via email to