You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Mark Hedges <he...@scriptdolphin.org> on 2009/01/01 15:23:26 UTC

a2c controller method names

> > - a lot of times people use references to other
> > structures when they should subclass... these references
> > function only to re-map arguments to other modules,
> > which is ridiculous.
>
>
> Careful on the should.  It can seem extra and possibly
> confusing but isn't always.  Delegation is a valid pattern
> that is cleaner than inheriting at times, particularly
> when you're mixing in a few different modules at the same
> time to do something.  If you're merely extending an
> existing, then yes, inheritance is good. 
> Multi-directional multi-inheritance can get really
> messy... (as I dug myself out of in development recently
> myself)  if you haven't read, at least scan...

Regarding your comment about inheritance vs. references -
something I hadn't thought much about.  A) I need to prefix
all my internal method names with 'a2c_' to stay out of
the controller namespace.  B) You can't have any controller
subroutines with the same names as anything in the
Apache2::Request* family, which (slightly) limits your
choice of allowable URL's.  But I think it's worth it so
that '$self' is the Apache object.  What do people think?

I wonder how easy it would be to add controller subroutine
attributes for which ones are allowed or not, ala Catalyst,
instead of the controller having to provide an
'allowed_methods' method.

Mark

Re: a2c controller method names

Posted by Mark Hedges <he...@scriptdolphin.org>.

On Fri, 2 Jan 2009, David Ihnen wrote:

> Mark Hedges wrote:
> > I wonder how easy it would be to add controller
> > subroutine attributes for which ones are allowed or not,
> > ala Catalyst, instead of the controller having to
> > provide an 'allowed_methods' method.
> >
>
> It would have been nicer as a dispatching framework if it
> either A. would instantiate my object (through a defined
> interface like ->new($server)) first THEN call the method
> or B. defined a hook-handle/decline interface not that
> different from apache so that I can custom define how you
> check for availability (rather than the :public list or
> ->can), instantiate if relevant, and call subroutines in
> my particular object.
>
> I guess I'm saying consider the interface flexibility as
> you design the framework - there may be interest in doing
> something in the realm of setup before calling the method.

I see.  I guess that was something like my original thought
of making you provide allowed_methods() which returns an
array.  It's not much harder to type than :public
everywhere, gives you a central list ("which methods are
allowed?" is easier to answer from looking at the top of the
package), gives you flexibility/dynamism/inheritance, and
the results get cached by Apache2::Controller::Funk in a
lookup hash.

So I will probably stick with requiring allowed_methods() in
the controller package instead of inventing an elaborate
mechanism to make this "easier."  Thanks for your input.

Mark

Re: a2c controller method names

Posted by David Ihnen <da...@norchemlab.com>.
Mark Hedges wrote:
> I wonder how easy it would be to add controller subroutine
> attributes for which ones are allowed or not, ala Catalyst,
> instead of the controller having to provide an
> 'allowed_methods' method.
>   
Sounds like something JSON::RPC::Server::CGI does with :private and 
:public modifiers on the subroutine definitions, I think they're called 
'fields', might be worth a look to see how they did that.

A thought on this matter particularly.

Though JSON::RPC::Server::CGI was just fine about calling my methods 
with its dispatch, it could not find the ability to instantiate my 
object first.  In fact, it always called them in static context with 
itself as the first parameter, which I found quite limiting.

This simply didn't work for my object structure and way I wanted to OOP 
the program.  (I got around it by making a static class that implimented 
an allowed_subroutines function that instantiated and effectively 
manually delegated calls to the appropriate subroutines, blowing the 
nice :public list right into irrelevancy)

It would have been nicer as a dispatching framework if it either A. 
would instantiate my object (through a defined interface like 
->new($server)) first THEN call the method or B. defined a 
hook-handle/decline interface not that different from apache so that I 
can custom define how you check for availability (rather than the 
:public list or ->can), instantiate if relevant, and call subroutines in 
my particular object.

I guess I'm saying consider the interface flexibility as you design the 
framework - there may be interest in doing something in the realm of 
setup before calling the method.

David


Re: a2c controller method names

Posted by Mark Hedges <he...@scriptdolphin.org>.
> > On Thu, 1 Jan 2009, Mark Hedges wrote: Talking to myself
> > again. I think I can make it work either way.
> > Apache2::Controller won't use Apache2::Request as a
> > base, but it will still instantiate the Apache2::Request
> > object and put it in $self->{r}.  Then if you want to
> > use Apache2::Request as a base in your controller module
> > to access those methods via $self, you can.  Otherwise,
> > don't.
>
> For a compromise between them you could also do the 'fake
> delegate' where your AUTOLOAD subroutine checks if
> $self->{r}->can(($AUTOLOAD =~ /::(.+?)$/)[0]) returns a
> CODE ref and delegates the call to that routine.

I don't want to use AUTOLOAD.  It adds latency and it
confuses the hell out of me when the method namespace gets
complicated.  You're free to use AUTOLOAD in controller
packages though.

> I think you're right, its better to be explicit about
> choosing the request object when you want to do a request
> object method.  That works find unless you're replicating
> some sort of interface where the methods you need directly
> callable are in two diff subclasses and inheritance
> doesn't do what you want and explicit delegation (wrapper
> methods) is too much of a PITA.

Yeah, this is why I usually spell things out instead of
using SUPER::.  In this case I've discovered it is in fact
important to get the inheritance order right.  As long as
Apache2::Request is the last base it comes out okay, new()
then creates the A2C handler object instead of trying to
make an Apache2::Request object.

> I would make myself a little method
>
> sub r { shift->{'r'} };
>
> just so I could write
>
> $self->r->...
>
> instead of having to do the hash dereference.  Of course,
> you can program that sort of thing in AUTOLOAD too.  ;)

You could do that in some app co-base that you write to
extend your controllers with convenience methods, if you
choose not to use Apache2::Request as a base to suck its
methods into $self.  But if you don't choose to do that,
dereferencing $self->{r} is faster than calling a method
that then does the same thing, so I probably won't provide
the convenience method.

Mark

Re: a2c controller method names

Posted by David Ihnen <da...@norchemlab.com>.
Mark Hedges wrote:
> On Thu, 1 Jan 2009, Mark Hedges wrote:
>   
>> Regarding your comment about inheritance vs. references -
>> something I hadn't thought much about.  A) I need to prefix
>> all my internal method names with 'a2c_' to stay out of
>> the controller namespace.  B) You can't have any controller
>> subroutines with the same names as anything in the
>> Apache2::Request* family, which (slightly) limits your
>> choice of allowable URL's.  But I think it's worth it so
>> that '$self' is the Apache object.  What do people think?
>>     
>
> Talking to myself again. I think I can make it work either
> way.  Apache2::Controller won't use Apache2::Request as a
> base, but it will still instantiate the Apache2::Request
> object and put it in $self->{r}.  Then if you want to use
> Apache2::Request as a base in your controller module to
> access those methods via $self, you can.  Otherwise, don't.
>   

For a compromise between them you could also do the 'fake delegate' 
where your AUTOLOAD subroutine checks if $self->{r}->can(($AUTOLOAD =~ 
/::(.+?)$/)[0]) returns a CODE ref and delegates the call to that routine.

The downside is that you're overlapping namespaces, as you mentioned 
before, which has its own complications.

I think you're right, its better to be explicit about choosing the 
request object when you want to do a request object method.  That works 
find unless you're replicating some sort of interface where the methods 
you need directly callable are in two diff subclasses and inheritance 
doesn't do what you want and explicit delegation (wrapper methods) is 
too much of a PITA.

I would make myself a little method

sub r { shift->{'r'} };

just so I could write

$self->r->...

instead of having to do the hash dereference.  Of course, you can 
program that sort of thing in AUTOLOAD too.  ;)

David


Re: a2c controller method names

Posted by Mark Hedges <he...@scriptdolphin.org>.

On Thu, 1 Jan 2009, Mark Hedges wrote:
>
> Regarding your comment about inheritance vs. references -
> something I hadn't thought much about.  A) I need to prefix
> all my internal method names with 'a2c_' to stay out of
> the controller namespace.  B) You can't have any controller
> subroutines with the same names as anything in the
> Apache2::Request* family, which (slightly) limits your
> choice of allowable URL's.  But I think it's worth it so
> that '$self' is the Apache object.  What do people think?

Talking to myself again. I think I can make it work either
way.  Apache2::Controller won't use Apache2::Request as a
base, but it will still instantiate the Apache2::Request
object and put it in $self->{r}.  Then if you want to use
Apache2::Request as a base in your controller module to
access those methods via $self, you can.  Otherwise, don't.

Mark