Maypole::Manual::Inheritance man page on Fedora

Man page or keyword search:  
man Server   31170 pages
apropos Keyword Search (all sections)
Output format
Fedora logo
[printable version]

Maypole::Manual::InherUsercContributed Perl DocMaypole::Manual::Inheritance(3)

NAME
       Maypole::Manual::Inheritance - structure of a Maypole application

DESCRIPTION
       Discusses the inheritance structure of a basic and a more advanced
       Maypole application.

CONVENTIONS
       inheritance
		   +
		   |
		+-   -+
		   |
		   +

       notes
	       target *-------- note about the target

       association
	       source ------> target

Structure of a standard Maypole application
       A minimal Maypole application (such as the Beer database example from
       the Maypole synopsis) consists of a custom driver (or controller) class
       (BeerDB.pm), a set of auto-generated model classes, and a view class:

		  THE DRIVER
						 +------- init() is a factory method,
			  1	 Maypole	 |	     it sets up the view
	  Maypole::Config <----- config();	 |		classes
	  model();		 init(); *-------+			     THE VIEW
	   |			 view_object(); -------+
	   |	+--------------* setup();	       |      Maypole::View::Base
	   |	|		    +		       |	      +
	   |	|		    |		       |     1	      |
	   |	|    PLUGINS	Apache::MVC *-----+    +-----> Maypole::View::TT
	   |	|	+	    +		  |		(or another view class)
	   |	|	|	    |		  |
	   |	|	+-----+-----+		  |
	   |	|	      |			  |
	   |	|	    BeerDB		  +----- or CGI::Maypole
	   |	|					  or MasonX:::Maypole
	   |	|
	   |   setup() is a factory method,
	   |	 it sets up the model
	   |	     classes
	   |
	   |						 THE MODEL
	   |
	   |  Maypole::Model::Base    Class::DBI
	   |		 +	       +      +
	   |		 |	       |      |
	   +-------> Maypole::Model::CDBI   Class::DBI::<db_driver>
			     +			   +
			     |			   |
		  +------------+--------+-------+---------+
		  |	       |	|	|	  |
	      BeerDB::Pub      |   BeerDB::Beer | BeerDB::Brewery
	      beers();	       |   pubs();	| beers();
			       |   brewery();	|
			       |   style();	|
		 BeerDB::Handpump		|
		 pub();			     BeerDB::Style
		 beer();		     beers();

   Ouch, that's a lot of inheritence!
       Yes, that's a lot of inheritence, at some point in the future -
       probably Maypole 3.x we will move to Class::C3

   What about Maypole::Application - loading plugins
       The main job of Maypole::Application is to insert the plugins into the
       hierarchy. It is also the responsibility of Maypole::Application to
       decide which frontend to use. It builds the list of plugins, then
       pushes them onto the driver's @ISA, then pushes the frontend onto the
       end of the driver's @ISA.  So method lookup first searches all the
       plugins, before searching the frontend and finally Maypole itself.

       From Maypole 2.11, Maypole::Application makes no appearance in the
       inheritance structure of a Maypole application. (In prior versions,
       Maypole::Application would make itself inherit the plugins, and then
       insert itself in the hierarchy, but this was unnecessary).

   Who builds the model?
       First, remember we are talking about the standard, unmodified Maypole
       here. It is possible, and common, to override some or all of this stage
       and build a customised model. See below - An advanced Maypole
       application - for one approach. Also, see Maypole's "setup_model()"
       method.

       The standard model is built in 3 stages.

       First, "Maypole::setup_model" calls "setup_database" on the Maypole
       model class, in this case Maypole::Model::CDBI. "setup_database" then
       uses Class::DBI::Loader to autogenerate individual Class::DBI classes
       for each of the tables in the database ("BeerDB::Beer", "BeerDB::Pub"
       etc).  Class::DBI::Loader identifies the appropriate Class::DBI
       subclass and inserts it into each of these table classes' @ISA (
       "Class::DBI::<db_driver>" in the diagrams)..

       Next, "Maypole::setup" pushes Maypole::Model::CDBI onto the @ISA array
       of each of these classes.

       Finally, the relationships among these tables are set up. Either do
       this manually, using the standard Class::DBI syntax for configuring
       table relationships, or try Class::DBI::Relationship (which you can use
       via Maypole::Plugin::Relationship). If you use the plugin, you need to
       set up the relationships configuration before calling "setup()". Be
       aware that some people like the convenience of
       Class::DBI::Relationship, others dislike the abstraction. YMMV.

An advanced Maypole application
       We'll call it "BeerDB2".

       Maypole is a framework, and you can replace different bits as you wish.
       So what follows is one example of good practice, other people may do
       things differently.

       We assume this application is being built from the ground up, but it
       will often be straightforward to adapt an existing Class::DBI
       application to this general model.

       The main idea is that the autogenerated Maypole model is used as a
       layer on top of a separate Class::DBI model. I am going to refer to
       this model as the 'Offline' model, and the Maypole classes as the
       'Maypole' model. The idea is that the Offline model can (potentially or
       in actuality) be used as part of another application, perhaps a command
       line program or a cron script, whatever.	 The Offline model does not
       know about the Maypole model, whereas the Maypole model does know about
       the Offline model.

       Let's call the offline model "OfflineBeer". As a traditional Class::DBI
       application, individual table classes in this model will inherit from a
       common base ("OfflineBeer"), which inherits from Class::DBI).

       One advantage of this approach is that you can still use Maypole's
       autogenerated model. Another is that you do not mix online and offline
       code in the same packages.

   Building it
       Build a driver in a similar way as for the basic app, calling "setup()"
       after setting up all the configuration.

       It is a good habit to use a custom Maypole model class for each
       application, as it's a likely first target for customisation. Start it
       like this:

	   package BeerDB2::Maypole::Model;
	   use strict;
	   use warnings;
	   use base 'Maypole::Model::CDBI';
	   1;

       You can add methods which should be shared by all table classes to this
       package as and when required.

       Configure it like this, before the "setup()" call in the driver class:

	   # in package BeerDB2
	   __PACKAGE__->config->model('BeerDB2::Maypole::Model');
	   __PACKAGE__->setup;

       The "setup()" call will ensure your custom model is loaded via
       "require".

       Note: by default, this will create Maypole/CDBI classes for all the
       tables in the database. You can control this by passing options for
       Class::DBI::Loader in the call to "setup()".

       For each class in the model, you need to create a separate file. So for
       "BeerDB2::Beer", you would write:

	   package BeerDB2::Beer;
	   use strict;
	   use warnings;
	   use base 'OfflineBeer::Beer';
	   1;

       From Maypole 2.11, this package will be loaded automatically during
       "setup()", and "BeerDB2::Maypole::Model" is pushed onto it's @ISA.

       Configure relationships either in the individual "OfflineBeer::*"
       classes, or else all together in "OfflineBeer" itself i.e. not in the
       Maypole model. This way, you only define the relationships in one
       place.

       The resulting model looks like this:

					      Class::DBI
	   MAYPOLE 'MODEL'			 |
						 |
	  Maypole::Model::Base			 |
		  +				 |
		  |	  +-----------------+----+-----------------+
		  |	  |		    |			   |
		  |	  |		    |			   |
	    Maypole::Model::CDBI	    |			   |	 OFFLINE
		    +			    |			   |	    MODEL
		    |			    |			   |
	    BeerDB2::Maypole::Model  Class::DBI::<db_driver>  OfflineBeer
	      +				    +			   +
	      |				    |			   |
	      +-----------------------------+			   |
	      |							   |
	      +--- BeerDB2::Pub --------+ OfflineBeer::Pub --------+
	      |				  beers();		   |
	      |							   |
	      |				  OfflineBeer::Handpump ---+
	      |				  beer();		   |
	      |				  pub();		   |
	      |							   |
	      +--- BeerDB2::Beer -------+ OfflineBeer::Beer -------+
	      |				  pubs();		   |
	      |				  brewery();		   |
	      |				  style();		   |
	      |							   |
	      +--- BeerDB2::Style ------+ OfflineBeer::Style ------+
	      |				  beers();		   |
	      |							   |
	      +--- BeerDB2::Brewery ----+ OfflineBeer::Brewery ----+
					  beers();

       Features

       1. Non-Maypole applications using the Offline model are completely
       isolated from the Maypole application, and need not know it exists at
       all.

       2. Methods defined in the Maypole table classes, override methods
       defined in the Offline table classes, because "BeerDB2::Maypole::Model"
       was pushed onto the end of each Maypole table class's @ISA. Perl's
       depth first, left-to-right method lookup from e.g. "BeerDB2::Beer"
       starts in "BeerDB2::Beer", then "BeerDB2::Maypole::Model",
       "Maypole::Model::CDBI", "Maypole::Model::Base", and "Class::DBI",
       before moving on to "OfflineBeer::Beer" and finally "OfflineBeer".

       CAVEAT - if your Offline model overrides Class::DBI methods, these
       methods will not be overridden when called from the Maypole
       application, because the Maypole model provides an alternative path to
       Class::DBI which is searched first. The solution is to place such
       methods in a separate package, e.g.  "OfflineBeer::CDBI". Place this
       first in the @ISA of both "BeerDB2::Maypole::Model" and "OfflineBeer".
       Note that "OfflineBeer::CDBI" does not itself need to inherit from
       Class::DBI.

       3. Methods defined in the Maypole model base class
       ("BeerDB2::Maypole::Model"), override methods in the individual Offline
       table classes, and in the Offline model base class ("Offline").

       4. Relationships defined in the Offline classes are inherited by the
       Maypole model.

       5. The Maypole model has full access to the underlying Offline model.

       Theory

       This layout illustrates more clearly why the Maypole model may be
       thought of as part of the controller, rather than part of the model of
       MVC. Its function is to mediate web requests, translating them into
       method calls on the Offline model, munging the results, and returning
       them via the Maypole request object.

       Another way of thinking about it is that Maypole implements a two-layer
       controller. The first layer translates a raw request into a single
       method call on the Maypole model layer, which then translates that call
       into one or more calls on the underlying model.

       Whatever label you prefer to use, this approach provides for clear
       separation of concerns between the underlying model and the web/user
       interface, and that's what it's all about.

Advanced applications - building the model by hand ** TODO
       - using Maypole::Model::CDBI::Plain or
       Maypole::FormBuilder::Model::Plain - setup_model() and
       load_model_subclass() - cutting out all those separate paths to CDBI -
       they're confusing

Method inheritance ** TODO
       More description of Perl's left-to-right, depth-first method lookup,
       and where it's particularly important in Maypole.

AUTHOR
       David Baird, "<cpan@riverside-cms.co.uk>"

COPYRIGHT & LICENSE
       Copyright 2005 David Baird, All Rights Reserved.

       This text is free documentation; you can redistribute it and/or modify
       it under the same terms as the Perl documentation itself.

perl v5.14.1			  2007-05-18   Maypole::Manual::Inheritance(3)
[top]

List of man pages available for Fedora

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net