MixinF...ReadMe(3pm)
π MixinF...ReadMe(3pm) β like, the whole tea on Class::MixinFactory π
okay bestie, gather round, because this is the Class::MixinFactory::ReadMe page and it is literally the "About the Mixin Class Factory" doc. yes, the manual is called MixinF...ReadMe(3pm) (they truncated it, iconic behavior) and it's filed under User Contributed Perl Documentation. we're gonna get you fluent in runtime mixin generation, no cap. π¦
β¨ NAME β¨
Class::MixinFactory::ReadMe β About the Mixin Class Factory. that's it, that's the name, she's self-describing π
β¨ SYNOPSIS β¨
here's the whole vibe in one code block, bestie. don't skip it:
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
see how the calls chain? that's the whole point, and we love her for it πΈ
β¨ ABSTRACT β¨
so this distribution? it facilitates the run-time generation of classes which inherit from a base class plus some optional selection of mixin classes. you pick the mixins at runtime, she builds the class for you.
there's a factory provided that generates the mixed classes with multiple inheritance. and there's a NEXT method that lets you redispatch up the inheritance chain. both of these things are doing the heavy lifting, periodt.
β¨ MOTIVATION β¨
π The Challenge
okay so when I'm developing an object class that different people are gonna use for different purposes, I keep getting drawn to the same shape of solution: a minimal base class that provides the shared behavior they all need, plus a collection of subclasses that layer on additional functionality.
like, think about a text templating framework. it might get 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
Safecompartment, - 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 it looks like this:
+---------+
| Base |
+---------+
|
+-----------------+-----------------+
v v v
+---------+ +---------+ +---------+
|Benchmark| | Filter | | Safe | @ISA=qw(Base)
+---------+ +---------+ +---------+
the well-known problem with this implementation shows up the SECOND 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 π and here's the actual question: 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 make sure they're all called in the correct sequence?? nobody knows. that's the problem. π
π 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. like, separate classes for a resolver, a lexer, a parser, a compiler, and an output channel. (see HTML::Mason for an example of this design.)
ngl 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, and one of those ways 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)
BUT. and this is a big but. in this condition our mixin classes can't call SUPER methods at all! π instead, another redispatch mechanism is needed β one that's able to back-track through the inheritance tree and explore other branches. (see NEXT for such an implementation.)
also: 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 make sure that the Benchmarking mixin was first in the chain, so that it could time everything later in the sequence. order matters, bestie, always has. π
π 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. and here's the cute part: 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'd 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 a 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. let's go down the list π
- the
mixin,Class::Mixin, andSpiffymodules support mixin classes but don't have a configurable factory object or support run-time mixin selection. - the
Class::MixandClass::Mutatormodules provide run-time class generation with multiple inheritance, but they don't provide a configurable factory object or a redispatch technique. - the
Class::Factorymodule has a factory interface, but doesn't support multiple inheritance. - the
NEXTmodule provides a backtracking equivalent toSUPERsimilar to theNEXTmethod included here, but usesAUTOLOADrather than a universal method. - the
Class::Delegateand other modules support decoration to address this problem via decomposition. - the
Class::Role,Class::RolesandClass::Traitmodules support composing shared behaviors into your class.
β¨ VERSION β¨
this is version 0.92 β¨
elements of the interface remain open to change. (so like, she's still growing, okay? be nice to her.)
β¨ 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. love that for us, zero drama, zero deps. π§
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
(that sudo make install at the end, she's doin' the most, but that's the procedure bestie.) π
β¨ 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. (a failing test case? that's the love language, fr fr.)
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.
and that's the whole page, bestie!! π this was MixinF...ReadMe(3pm) from User Contributed Perl Documentation, perl v5.36.0, dated 2022-10-22. bye bye, go build something with runtime mixins, mwah πβ¨
π¦ where this page comes from
- ubuntu noble: libclass-mixinfactory-perl 0.92-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libclass-mixinfactory-perl 0.92-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libclass-mixinfactory-perl 0.92-5 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms