Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
MixinFactory::ReadMe(3User Contributed Perl DocumentatiMixinFactory::ReadMe(3)

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

	 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

       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

   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:

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

       o   an extension	which enhances security	by runing the code in a	Safe

       o   an extension	which feeds output through an HTML-escaping filter,

       o   an extension	which records internal profiling data for benchmarking

       (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)
	 +---------+	   +---------+	     +---------+
				|		  |
				  | 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	 |
	 +---------+	   +---------+	     +---------+       +---------+
				|		  |		    |
					   | 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 serveral elements to
       facilitate tihs 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

       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

       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.)

       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.

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

       o   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.

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

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

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

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

       This is version 0.92.

       Elements	of the interface remain	open to	change.

       This module is new and relatively untested.

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

       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

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

       Alternately, you	may retrieve this package from CPAN
       ("")	or from	the author's site

       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

       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
       "" or	send
       mail to "", 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

       For more	general	discussion, you	may wish to post a message on
       PerlMonks ("")
       or on the comp.lang.perl.misc newsgroup

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

       Custom development and technical	consulting are available at
       "". More free Perl software is	available at

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

       Copyright 2004 Matthew Simon Cavalletto.

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

perl v5.32.1			  2004-11-19	       MixinFactory::ReadMe(3)


Want to link to this manual page? Use this URL:

home | help