Provided by: libclass-mixinfactory-perl_0.92-3_all bug

NAME

       Class::MixinFactory::ReadMe - About the Mixin Class Factory

SYNOPSIS

         package MyClass;
         use Class::MixinFactory -hasafactory;
         sub new { ... }
         sub foo { return "Foo Bar" }

         package MyClass::Logging;
         sub foo { warn "Calling foo"; (shift)->NEXT('foo', @_) }

         package MyClass::UpperCase;
         sub foo { uc( (shift)->NEXT('foo', @_) ) }

         package main;

         my $class = MyClass->class( 'Logging', 'UpperCase' );

         print $class->new()->foo();
         # Calls MyClass::Logging::foo, MyClass::UpperCase::foo, MyClass::foo

ABSTRACT

       This distribution facilitates the run-time generation of classes which inherit from a base
       class and some optional selection of mixin classes.

       A factory is provided to generate the mixed classes with multiple inheritance.  A NEXT
       method allows method redispatch up the inheritance chain.

MOTIVATION

   The Challenge
       When developing an object class that will be used by different people for different
       purposes, I find myself drawn to solutions in which a minimal base class provides the
       shared behavior they all need, and a collection of subclasses provides layers of
       additional functionality.

       For example, consider a text templating framework, which might be separated into several
       elements:

       •   a base class, which provides methods to convert marked-up text into runnable code,

       •   an extension which enhances security by running the code in a Safe compartment,

       •   an extension which feeds output through an HTML-escaping filter, and

       •   an extension which records internal profiling data for benchmarking purposes.

       (See Text::MicroMason for an example of this design.)

   A Bad Approach
       A naive implementation of this might use a subclass for each behaviour, and look like the
       following:

                           +---------+
                           |   Base  |
                           +---------+
                                |
              +-----------------+-----------------+
              v                 v                 v
         +---------+       +---------+       +---------+
         |Benchmark|       |  Filter |       |   Safe  | @ISA=qw(Base)
         +---------+       +---------+       +---------+

       The well-known problem with this implementation appears when you want to combine several
       features:

                           +---------+
                           |   Base  |
                           +---------+
                                |
              +-----------------+-----------------+
              v                 v                 v
         +---------+       +---------+       +---------+
         |Benchmark|       |  Filter |       |   Safe  | @ISA=qw(Base)
         +---------+       +---------+       +---------+
                                |                 |
                                +--------+--------+
                                         v
                                  +-------------+
                                  | Safe_Filter | @ISA=qw(Filter Safe)
                                  +-------------+

       This is the dreaded "diamond inheritance" problem: if Base provides a compile() method,
       which Filter and Safe each override to perform additional actions before or after calling
       SUPER::compile(), how can we ensure they are all called in the correct sequence?

   A Good Approach
       The standard software engineering solution is to replace the use of inheritance with
       decomposition into several different classes of objects, which then cooperate through
       decoration and delegation; for example, using separate classes for a resolver, a lexer, a
       parser, a compiler, and an output channel. (See HTML::Mason for an example of this
       design.)

       Indeed, composition is an underutilized design technique, and there are many times when
       inheritance is not the best tool to use. But of course, in Perl there's more than one way
       to solve this problem, one of which is facilitated by this distribution.

   A Different Approach
       We can rearrange our class hierarchy to avoid diamond inheritance by using a base and a
       collection of mixin classes, which don't directly inherit from the base class:

         +---------+       +---------+       +---------+       +---------+
         |Benchmark|       |  Filter |       |   Safe  |       |   Base  |
         +---------+       +---------+       +---------+       +---------+
                                |                 |                 |
                                +-----------------+-----------------+
                                                  v
                                           +-------------+
                                           | Safe_Filter | @ISA=qw(Filter
                                           +-------------+     Safe Base)

       However, in this condition our mixin classes can't call SUPER methods at all! Instead,
       another redispatch mechanism is needed, one that is able to back-track through the
       inheritance tree and explore other branches. (See NEXT for such an implementation.)

       The order in which mixins are stacked is significant, so the caller does need to have some
       understanding of how their behaviors interact. For example, you'd typically want to ensure
       that the Benchmarking mixin was the first in the chain, so that it could time everything
       later in the sequence.

   This Distribution
       The Class::MixinFactory distribution provides several elements to facilitate this kind of
       dynamic mixin architecture. The top level package is just a facade that loads the other
       necessary classes and provides a few import options for compile-time convenience. (See
       Class::MixinFactory.)

       To generate an object with some combination of mixins, you first use a mixin factory to
       generate a mixed class. If a class with that combination of classes has already been
       created, it is reused. You can add a factory method to your base class, create a separate
       factory object, or inherit to produce a factory class. (See Class::MixinFactory::Factory.)

       To allow mixin classes to redispatch to subsequent classes, all mixed classes also inherit
       from a class which provides a NEXT() method. (If you would prefer, your mixin class can
       alternately use the AUTOLOAD solution provided by the NEXT::ACTUAL module from CPAN, or
       any other equivalent re-dispatch mechanism.) (See Class::MixinFactory::NEXT.)

RELATED MODULES

       There are number of other modules on CPAN that also support mixins, method importing, or
       run-time multiple inheritance, while others don't use mixins but are addressing a similar
       area of concern.

       •   The mixin, Class::Mixin, and Spiffy modules support mixin classes but don't have a
           configurable factory object or support run-time mixin selection.

       •   The Class::Mix and Class::Mutator modules provide run-time class generation with
           multiple inheritance, but don't provide a configurable factory object or a redispatch
           technique.

       •   The Class::Factory module has a factory interface, but doesn't support multiple
           inheritance.

       •   The NEXT module provides a backtracking equivalent to SUPER similar to the NEXT method
           included here, but uses AUTOLOAD rather than a universal method.

       •   The Class::Delegate and other modules support decoration to address this problem via
           decomposition.

       •   The Class::Role, Class::Roles and Class::Trait modules support composing shared
           behaviors into your class.

VERSION

       This is version 0.92.

       Elements of the interface remain open to change.

BUGS

       This module is new and relatively untested.

       Please report any problems you encounter to the author at the below address.

INSTALLATION

       This module should work with any version of Perl 5, without platform dependencies or
       additional modules beyond the core distribution.

       You should be able to install this module using the CPAN shell interface:

         perl -MCPAN -e 'install Class::MixinFactory'

       Alternately, you may retrieve this package from CPAN ("http://search.cpan.org/~evo/") or
       from the author's site ("http://www.evoscript.org/Class-MixinFactory").

       After downloading the distribution, follow the normal procedure to unpack and install it,
       using the commands shown below or their local equivalents on your system:

         tar xzf Class-MixinFactory-*.tar.gz
         cd Class-MixinFactory-*
         perl Makefile.PL
         make test && sudo make install

SUPPORT

       If you have questions or feedback about this module, please feel free to contact the
       author at the below address. Although there is no formal support program, I do attempt to
       answer email promptly.

       I would be particularly interested in any suggestions towards improving the documentation,
       correcting any Perl-version or platform dependencies, as well as general feedback and
       suggested additions.

       Bug reports that contain a failing test case are greatly appreciated, and suggested
       patches will be promptly considered for inclusion in future releases.

       To report bugs via the CPAN web tracking system, go to
       "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Class-MixinFactory" or send mail to
       "Dist=Class-MixinFactory#rt.cpan.org", replacing "#" with "@".

       If you've found this module useful or have feedback about your experience with it,
       consider sharing your opinion with other Perl users by posting your comment to CPAN's
       ratings system ("http://cpanratings.perl.org/rate/?distribution=Class-MixinFactory").

       For more general discussion, you may wish to post a message on PerlMonks
       ("http://perlmonks.org/?node=Seekers%20of%20Perl%20Wisdom") or on the comp.lang.perl.misc
       newsgroup ("http://groups.google.com/groups?group=comp.lang.perl.misc").

AUTHOR

       Developed by Matthew Simon Cavalletto at Evolution Softworks.  You may contact the author
       directly at "evo#cpan.org" or "simonm#cavalletto.org", replacing "#" with "@".

       Custom development and technical consulting are available at "www.evolutionsoftworks.com".
       More free Perl software is available at "www.evoscript.org".

THANKS

       My sincere thanks to the Perl Monks community for their feedback on earlier versions of
       this commentary.

         http://perlmonks.org/index.pl?node_id=398061
         http://perlmonks.org/index.pl?node_id=399040

LICENSE

       Copyright 2004 Matthew Simon Cavalletto.

       You may use, modify, and distribute this software under the same terms as Perl.