Re: Plugin architecture

[email protected] ("Christopher J. Madsen")
Newsgroups perl.module.build
Message-ID <[email protected]>
Eric Wilhelm wrote:
> It is still difficult to debug, regardless of hope or intent.  If the 
> user breaks something via their config, a loud and obvious error should 
> result.

Two problems:  Just because a pre hook decided to override the method, 
and there were other pre hooks that didn't get called, it doesn't prove 
that anything's wrong.  Perhaps the processing that those hooks would 
have done is unnecessary in this case.  I don't see any way for Perl to 
decide.  I suppose we could print a warning, but what if a maintainer 
picks 2 plugins that cause that warning, but he knows that it's ok?  How 
can he suppress the warning?  (Maybe we should print the warning only if 
the overriding hook came from a system/user plugin.)

Second, my primary goal is that a plugin should be able to do anything a 
subclass can do.  This includes creating situations that are very 
difficult to debug.  The only way to make something impossible to abuse 
is to make it too restricted to do many things that would be useful.

> Similarly, maybe the priority should simply be by load-order.  At least 
> then a plugin which knows it is incompatible with another can make 
> noise.  Still it might be nice to have the noise created via some 
> mechanism in the registration (e.g. "conflicts => {Foo => '<= 0.2'}".)

One problem is that conflicts probably wouldn't be discovered until both 
plugins have been released.  A conflicts mechanism wouldn't do anything 
to help people who only installed the initial release.  I don't recall 
ever seeing M::B's conflicts mechanism actually used.

Load-order would be sufficient for plugins in Build.PL, although that 
means we'd have to use an arrayref instead of a hashref like everything 
else uses.

For the system config, I suppose we could split it in two sections: 
higher priority than Build.PL and lower priority than Build.PL.  But 
then the user config would need 4 sections:
   1. Higher than system
   2. Between system & Build
   3. Between Build & system
   4. Lower than Build

And what about plugins specified on the command line?

> Maybe the short-circuit (bypassing/replacing the default method) should 
> just be defined differently.  That is: replace_METHOD() or something 
> and only allow one definition of it.

The problem is that a pre hook may want to override the default method 
only for certain input parameters.  And another pre hook might want to 
override for other input parameters.  All-or-nothing is too restrictive.

> A few concrete examples would certainly help me work through that logic.

A pre hook is the equivalent of this method in a subclass:

sub method {
   my $self = shift;
   ... do stuff ...
   if (want to override) { return $something }
   $self->SUPER::method(@_); # @_ might have been modified
}

A post hook is the equivalent of this:

sub method {
   my $self = shift;
   my $return = $self->SUPER::method(@_); # I'm ignoring context here
   ... do stuff ...
   return $return;  # Might be modified
}

If you want to do stuff before and after SUPER::method, you install both 
hooks.  (Plugins aren't completely identical to this, because all post 
hooks get called even if a pre hook decided to override.  But they're 
close.)

-- 
Chris Madsen                                          [email protected]
   --------------------  http://www.cjmweb.net  --------------------
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.