You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by "Rafiq Ismail (ADMIN)" <ra...@joshua.dreamthought.com> on 2002/05/29 12:59:12 UTC

MVC advice..?

Hi,

I'm building an MVC architecture site and have hit a design issue.  I have
varoius Control subclasses which relate to different templates with
different behaviour.  Now my problem is that I have to assign which
Subclass I want to instantiate, based on the script and params.  I my last
effort I went for a Shared datastructure holding (script, control module
pairs) which then allowed one to be dynamically "eval 'use..'"'ed in the
main content handler.  I found that clunky.  I'm building from scratch
again and am thinking of just firing up a template and allowing the
control to be loaded INTO the view as a template toolkit plugin.  What I
hate about this is that I'm surrendering my View layer.

Is there a neat way of dynamically loading in the appropriate control
subclass?  Something proven and widely used.

Cheers,

Fiq

"__  __           _                 __  __
|  \/  | ___   __| | ___ _ __ _ __ |  \/  | __ _ _ __
| |\/| |/ _ \ / _` |/ _ \ '__| '_ \| |\/| |/ _` | '_ \
| |  | | (_) | (_| |  __/ |  | | | | |  | | (_| | | | |
|_|  |_|\___/ \__,_|\___|_|  |_| |_|_|  |_|\__,_|_| |_|
 	a pathetic example of his organic heritage"
		- Bad Religion




Re: MVC advice..?

Posted by Andy Wardley <ab...@andywardley.com>.
On Wed, May 29, 2002 at 11:11:59AM -0500, Dave Rolsky wrote:
> If require is given a string, it looks for a filename _matching_ that
> string.  If it's given a bareword, it converts '::' to filesystem path
> separators first.

<pedantic>

...and appends '.pm' onto the end.

Thus
    require Foo::Bar

is the same as:
    $module = 'Foo::Bar';
    $module =~ s[::][/]g;
    $module .= '.pm';
    require $module;

If you 'use' the module, then it also does the equivalent of:
    $module->import();

</pedantic>

A


Re: MVC advice..?

Posted by Perrin Harkins <pe...@elem.com>.
Rafiq Ismail (ADMIN) wrote:
> I'm not so keen on loading all the inheriting classes into memory
> beforehand

You really should do that, because it will save overall memory by 
increasing the amount of memory that's shared.  All modules should be 
loaded during startup in the parent process.

> It's a
> fairly large site and my main concern was to do with how I should store
> the correspondence from uri to object.

The httpd.conf format seems about as simple as you can get to me.  It's 
pretty unusual for a site to have dozens of controllers, and it usually 
indicates a design problem.  Apache::Dispatch is fine too.

> How does StatINC behave with 'required' packages?

Require and use are very similar and both add the loaded module to %INC. 
  Read 'perldoc -f use' for the exact differences.

- Perrin


Re: MVC advice..?

Posted by "Rafiq Ismail (ADMIN)" <ra...@joshua.dreamthought.com>.
Ello,

On 29 May 2002, Randal L. Schwartz wrote:

> >>>>> "Rafiq" == Rafiq Ismail (ADMIN) <ra...@joshua.dreamthought.com>
writes:
> Rafiq> Is there a neat way of dynamically loading in the appropriate
control
> Rafiq> subclass?  Something proven and widely used.
>
> Load the file with a require, and then just call the appropriate
> constructor using an indirect call:
>
>         require "My/Prefix/$type"; # presuming $type has no colons
>         $myClass = "My::Prefix::$type";
>         my $handler = $myClass->new(@parms);
>
> This works even in "use strict".

Thanks.  This is pretty much the handler which I'd previously written,
with the the exception of s/use/require/.  I'll probably either go with
Apache::Dispatch, using the DispatchRequire option, or write something
custom.


On Wed, 29 May 2002, Perrin Harkins wrote:
> So, you're asking how to map URLs to perl modules?  Is there some reason
> you aren't simply using httpd.conf or Apache::Dispatch?  In my last MVC

I just took a look at Apache::Dispatch and I get he impression that if I
were to use it then I would have to either PerlModule 'all' my subclasses
beforehand, or alternateively use the DispatchRequire option anyway.  I'm
already using StatINC so I'm going to have to do a toss between code which
I've already written and converging to the Apache::Dispatch interface.

I'm not so keen on loading all the inheriting classes into memory
beforehand, nor setting up multiple handlers for each location.  It's a
fairly large site and my main concern was to do with how I should store
the correspondence from uri to object.


> design, we had all of our controllers inherit from one base controller
> that held all of the common code.

I could just map from URLs to the specific control subclasses and then use
Dispatch to require them - I'd already started on writing a mapping from
path names to relative namespaces.  I was still 'eval/use'ing the
Modules though.

How does StatINC behave with 'required' packages?

Hmm.. it's "make your mind up time. ;)


Thanks for the tips.
Cheers,

Fiq

__
"__  __           _                 __  __
|  \/  | ___   __| | ___ _ __ _ __ |  \/  | __ _ _ __
| |\/| |/ _ \ / _` |/ _ \ '__| '_ \| |\/| |/ _` | '_ \
| |  | | (_) | (_| |  __/ |  | | | | |  | | (_| | | | |
|_|  |_|\___/ \__,_|\___|_|  |_| |_|_|  |_|\__,_|_| |_|
 	a pathetic example of his organic heritage"
		- Bad Religion


Re: MVC advice..?

Posted by Perrin Harkins <pe...@elem.com>.
Dave Rolsky wrote:
> On Wed, 29 May 2002, Perrin Harkins wrote:
> 
> 
>>There's no good reason to do an eval 'use'.  Use require instead, and
>>import if you need to (but most people don't).
> 
> 
> Actually, there is.  This code:
> 
>   my $module = 'Foo::Bar';
>   require $module;
> 
> is not the same as this:
> 
>   require Foo::Bar;
> 
> If require is given a string, it looks for a filename _matching_ that
> string.  If it's given a bareword, it converts '::' to filesystem path
> separators first.

Then do an eval 'require Foo::Bar', but eval 'use Foo::Bar' doesn't make 
sense.

- Perrin


Re: MVC advice..?

Posted by Dave Rolsky <au...@urth.org>.
On Wed, 29 May 2002, Perrin Harkins wrote:

> There's no good reason to do an eval 'use'.  Use require instead, and
> import if you need to (but most people don't).

Actually, there is.  This code:

  my $module = 'Foo::Bar';
  require $module;

is not the same as this:

  require Foo::Bar;

If require is given a string, it looks for a filename _matching_ that
string.  If it's given a bareword, it converts '::' to filesystem path
separators first.


-dave

/*==================
www.urth.org
we await the New Sun
==================*/


Re: MVC advice..?

Posted by Perrin Harkins <pe...@elem.com>.
Rafiq Ismail (ADMIN) wrote:
> Now my problem is that I have to assign which
> Subclass I want to instantiate, based on the script and params.

So, you're asking how to map URLs to perl modules?  Is there some reason 
you aren't simply using httpd.conf or Apache::Dispatch?  In my last MVC 
design, we had all of our controllers inherit from one base controller 
that held all of the common code.  Then we could just map from URLs to 
the specific controllers that handled them:

<Location /mycontroller>
   SetHandler  perl-script
   PerlHandler My::Controller
</Location>

> I my last
> effort I went for a Shared datastructure holding (script, control module
> pairs) which then allowed one to be dynamically "eval 'use..'"'ed in the
> main content handler.  I found that clunky.

There's no good reason to do an eval 'use'.  Use require instead, and 
import if you need to (but most people don't).

> I'm building from scratch
> again and am thinking of just firing up a template and allowing the
> control to be loaded INTO the view as a template toolkit plugin.  What I
> hate about this is that I'm surrendering my View layer.

I agree, that's a bad idea and certainly not MVC.

- Perrin


Re: MVC advice..?

Posted by "F.Xavier Noria" <fx...@isoco.com>.
On Wed, 29 May 2002 09:22:00 -0400
"Aaron Ross" <ro...@alias-i.com> wrote:

: > Is there a neat way of dynamically loading in the appropriate control
: > subclass?  Something proven and widely used.
: 
: For what it's worth, I use the eval trick too.  Although it may seem a
: little clunky, I believe it is "proven and widely used".  The DBI.pm
: module uses code like this to load in the DBD drivers:
: 
:     my $driver_class = "DBD::$driver";
:     eval "package DBI::_firesafe; require $driver_class";

I wonder, why do you program such a central module that dynamic? Why
do you chose that approach instead of this one?

     package Dispatcher;

     use Controller1;
     # ...
     use ControllerN;

     sub handler {
         my $r = Apache::Request->new(shift);
         my $ctl = $r->param('ctl');

         return Controller1::handler($r) if $ctl = 'login';
         # ...
         return ControllerN::handler($r) if $ctl = 'show_cart';
         return SERVER_ERROR;
     }

-- fxn

RE: MVC advice..?

Posted by Aaron Ross <ro...@alias-i.com>.
> Is there a neat way of dynamically loading in the appropriate control
> subclass?  Something proven and widely used.

For what it's worth, I use the eval trick too.  Although it may seem a
little clunky, I believe it is "proven and widely used".  The DBI.pm
module uses code like this to load in the DBD drivers:

    my $driver_class = "DBD::$driver";
    eval "package DBI::_firesafe; require $driver_class";

I'm not sure this answers your MVC questions, but maybe it will make you
feel more comfortable with your solution.

hth, aaron