Terrence Brannon | 5 Dec 03:18

two alternate approaches to mixin functionality


NAME
    Class::MixinFactory::alternatives - approaches to the same functionality

DESCRIPTION
    A recent contribution to CPAN is Class::MixinFactory by Simon Cavaletto.
    Here we show two more ways to do the same thing in addition to the ones
    that Simon lists in the SEE ALSO section.

    One method relies on Leon Brocard's Language::Functional. The other
    relies on Toby Ovod-Everett's Class::Prototyped.

ALTERNATIVE IMPLMENTATIONS
    I include here a file, which when run, produces output similar to the
    output from factory_class.t in the Class::MixinFactory distribution.

    It shows two new ways of doing this, the Language::Functional approach
    and the Class::Prototyped approach.

     # 
     # lf.pl
     #

     use strict;

     use Language::Functional ':all';

     sub  _uc    { uc shift } ;
     sub bold    { sprintf "<b>%s</b>", shift } ;
     sub italics { sprintf "<i>%s</i>", shift } ;
(Continue reading)

Gravatar

Re: two alternate approaches to mixin functionality

On Saturday, December 4, 2004, at 09:18  PM, Terrence Brannon wrote:

>     A recent contribution to CPAN is Class::MixinFactory by Simon 
> Cavaletto.
>     Here we show two more ways to do the same thing in addition to the 
> ones
>     that Simon lists in the SEE ALSO section.

Terrence -- Thanks for your article, and for your attention to this 
issue.

However, I'm not convinced that these alternatives "do the same thing" 
as Class::MixinFactory on other than a very abstract level.

Both of the examples use foldl() to chain several function calls 
together, but they don't do any of the following:

1. Create polymorphic instances, which hide different behaviors behind
    an identical-looking simple calling interface;

2. Allow behaviors for several functions to be grouped together, so
    that one user-selectable option can influence multiple methods;

3. Allow behaviors to control how items later in the chain are called,
    so that they can wrap them in an eval, cache the results, do
    something before the call and then clean up after, etc.

Issue 1 is fairly easy to address, by replacing the foldl call with a 
call to a dynamically built single function that calls a selection of 
others, and I've included some sample code in a post-script below that 
(Continue reading)

Mark Stosberg | 6 Dec 01:42
Picon
Favicon
Gravatar

Re: two alternate approaches to mixin functionality

On 2004-12-05, Terrence Brannon <bauhaus@...> wrote:
>
>
> NAME
>     Class::MixinFactory::alternatives - approaches to the same functionality
>
> DESCRIPTION
>     A recent contribution to CPAN is Class::MixinFactory by Simon Cavaletto.
>     Here we show two more ways to do the same thing in addition to the ones
>     that Simon lists in the SEE ALSO section.

What thoughts do people have on the solution that uses standard export
techniques without extra modules?  This is what CGI::Application Plugins do
now.

What to mixin a CGI::Application plug-in? 

 use CGI::Application::Plugin::ValidateRM (qw/check_rm/);

That's it. It's mostly a standard 'has-a' relationship. 

The only thing slightly unique going on is that the imported

functions expect the first argument to be a CGI::Application compatible
object. 

You can mix-in these methods and then have them later inherited, or just
use them directly in the children.

So far I've seen that's very clear to the CGI::App users and the plug-in
(Continue reading)

Gravatar

Re: two alternate approaches to mixin functionality

On Sunday, December 5, 2004, at 07:42  PM, Mark Stosberg wrote:

> What thoughts do people have on the solution that uses standard export
> techniques without extra modules?  This is what CGI::Application 
> Plugins do
> now.

Yup; this "method exporting" is a workable solution that I've used in 
the past, and it seems a reasonable choice if your callers are building 
their own subclasses anyway.

Because you're importing those methods into custom constructed 
subclasses of CGI::Application, this implementation doesn't suffer from 
the worst of the namespace confusion that Stevan referred to in his 
reply.

A second area of concern is that it lacks a clear re-dispatch mechanism 
to allow the plugins/mixins to invoke underlying behaviors. For 
example, a mixin can't simply override a built-in method to provide 
benchmarking information:

   package CGI::Appliction::Plugin::RunTimeLog;
   @EXPORT = 'run';
   sub import { goto Exporter::import }

   sub run {
     my $start = Benchmark->new();
     (shift)->SUPER::run( @_ );    # <== XXX dies here XXX
     warn "Run: " . timestr( $start->timediff( Benchmark->new() ) )
   }
(Continue reading)

Mark Stosberg | 10 Dec 03:47
Picon
Favicon
Gravatar

Re: two alternate approaches to mixin functionality

On 2004-12-08, Matthew Simon Cavalletto <simonm@...> wrote:
>
> Yup; this "method exporting" is a workable solution that I've used in 
> the past, and it seems a reasonable choice if your callers are building 
> their own subclasses anyway.

That is typically the case with CGI::Applicaton. 

> A second area of concern is that it lacks a clear re-dispatch mechanism 
> to allow the plugins/mixins to invoke underlying behaviors. For 
> example, a mixin can't simply override a built-in method to provide 
> benchmarking information:
>
>    package CGI::Appliction::Plugin::RunTimeLog;
>    @EXPORT = 'run';
>    sub import { goto Exporter::import }

Why the non-standard Exporter syntax? The docs recommend:

 @ISA = qw(Exporter);
 @EXPORT_OK = qw(munge frobnicate);  # symbols to export on request

>    sub run {
>      my $start = Benchmark->new();
>      (shift)->SUPER::run( @_ );    # <== XXX dies here XXX
>      warn "Run: " . timestr( $start->timediff( Benchmark->new() ) )
>    }

There is a proposal to handle this in part with
CGI::Application::Callbacks:
(Continue reading)

Stevan Little | 6 Dec 05:37
Favicon

Re: Re: two alternate approaches to mixin functionality

Mark,

On Dec 5, 2004, at 7:42 PM, Mark Stosberg wrote:
> What thoughts do people have on the solution that uses standard export
> techniques without extra modules?  This is what CGI::Application  
> Plugins do
> now.

This approach is indeed simple to use and understand, but I also think  
it has a number limitations.

<disclaimer>
I am not familiar with the details of CGI::Applications's plugins so I  
may be off here. My assumption is that the plug-ins import themselves  
into the CGI::Application namespace (or a subclass of CGI::Application  
maybe).
</disclaimer>

Anyway, this technique has all the frailty of most other mix-in  
technologies in that its injecting methods into the class hierarchy in  
an arbitrary way. This makes it difficult to have much control over the  
hierarchy since at any point a mix-in can just inject functionality  
into the middle of it. This also makes debugging difficult since you  
now have methods coming at you from all sides. IMO this just gets too  
messy and impossible to control in any meaningful way.

If you have a well defined plug-in API and a set of overridable methods  
then this can work, since this becomes a predictable thing. But at that  
point you are not using general purpose mix-ins, but specific  
constrainted plug-ins.
(Continue reading)

Terrence Brannon | 5 Dec 05:06

GMANE feed now available


You can now read/post this mailing via GMANE:

    http://dir.gmane.org/gmane.comp.lang.perl.software-design

--
	Carter's Compass: I know I'm on the right track when,
	   by deleting something, I'm adding functionality.

Gmane