> > Well, we're not really talking about inheritance, in the classic
sense.
> > We're more discussing the Decorator pattern (for Gang of Four).
> > C::A::Foo and C::A::Bar are really adding capabilities to C::A.
> > Discussing inheritance is actually clouding the picture.
>
> That is a nice consise way of describing exactly what I was thinking
:)
Thank you. :-)
> > What about considering the 3rd-party plugins as delegates vs.
> > subclasses? C::A::MySuperClass would be a subclass of C::A, but
> > C::A::Session or C::A::DBI (for example) would not. They would,
instead,
> > register on use() with C::A (using some register method).
Registration
> > would indicate the following:
> > 1) What portions of the pipeline they need access to (the standard
areas
> > would probably be good enough for starters)
> > 2) What method within the class needs to be called at that point
> > 3) When that method need to be called in relation to the other
methods
> > (Use the Apache FIRST, MIDDLE, LAST, REALLY_FIRST, REALLY_LAST
options
> > here)
>
> This is also the direction that I was heading, but you have explained
it
> beautifully.
And, thank you again.
> > Registration would also have the effect of instantiating that class
and
> > saving off the object. I'm assuming that these classes will be
> > singletons, with some being factories, as needed. For example,
> > C::A::Session would actually register C::A::Session::Factory with
C::A,
> > and it would create C::A::Session objects on each request, as
needed.
> >
> > Part of the issue I'm having with discussing the pipeline is that I
> > haven't seen what it is we're passing down the pipe from handler to
> > handler. In Apache, the pipeline passes an Apache::Request object
from
> > the first bucket to the last. Every handler deals with $r, modifying
it
> > as needed.
>
> I guess we would just be passing the CGI::Application object around
> through the pipeline (which happens currently through $self). This is
> really what mod_perl is doing as well, it is just that they call the
> object $r. Also, a minor correction, it is an 'Apache' object that is
> passed to handlers, or retrieved by calling Apache->request or
> Apache->instance. Apache::Request is more like a decorator class you
> describe above by adding CGI parameter handling and file uploading
> capabilities to the 'Apache' object. A minor nit, but it gives
another
> example of what you explained to us above.
That would work. C::A would need to expose the request (in pre-run
hooks) and the content (in post-run hooks). But, that shouldn't be too
hard, especially given the param() method. It does initially seem a
little bootstrap-ish to have delegates register with C::A, then have
C::A pass itself to what it's controlling, but I prefer to think of it
in this fashion:
C::A (the class) knows of people who are experts in their field. It
wants to ask their advice on how to do with a given situation (C::A, the
instance). It completely trusts the expert to do what is needed, all of
what is needed, and only what is needed.
In that vein, I would like to note that we probably don't need to
provide any checking of activity taken. I'd actually say we don't want
to. All the "experts" are explicitly activated by the C::A client. So,
they're trusted by the entity controlling C::A, so C::A should trust
them.
> > There's also the capability of declining to handle this situation.
The
> > classic example here is an output filter which cleans HTML. If the
> > content-type isn't text/html, the filter declines to handle this
> > request.
>
> But the filter/hook would still be executed, it just decides not to do
> anything and returns right away.
>
> > By adding the concepts of OK, DECLINED, and NOK, we gain the ability
of
> > adding additional modules, such as C::A::Security. Right now, in my
> > C::A, I have a App::User object which determines if someone is
allowed
> > in. I'd prefer to delegate that responsibility to C::A::Security.
(I'd
> > actual want to delegate that responsibility to Apache, but I can't,
for
> > legacy issues.)
>
> This would only work if there is some decision making system built in
> that decides what to do if a hook returns a DECLINED instead of an OK
> (ie do I stop processing the rest of the chain? Do I return an
error?)
> To use mod_perl as an example again, say we have three TransHandlers
> hooked in to process a request. The first returns DECLINED which
tells
> Apache that this stage is not complete yet and so it also executes the
> second one. If the second one returns OK, then the third one is never
> executed. On the other hand, if we added three FixupHandlers, then
the
> return value is not relevant, because all handlers are executed
> regardless (unless a fatal error occurs). These decisions are clearly
> defined in the Apache request cycle.
>
> I don't know if we really have that sort of a structure in the
> CGI::Application pipeline. I would expect every registered hook to be
> executed at each of the stages (setup, init, prerun, postrun,
teardown)
> regardless of whether it completed its task succesfully.
The bigger question is if we would want that kind of structure in the
pipeline. I agree that it probably isn't necessary. The decision of
whether any actions should be taken should be handled by the expert, not
by C::A who is, after all, the one asking for advice! This puts the onus
on the developer of the delegate, which is ok.
> Now I do believe that the state of the application could be changed by
a
> hook. Right now in a prerun method you can change the current runmode
> to something else, so something like that should still be possible.
If the C::A state (which includes the request and the response) wasn't
mutable by the hooks, what would be the point of them? I am thinking
that this redesign would be a generalization of the current
overloadable-hook setup. As for how, I would think that C::A would
provide lightweight objects for each of its state attributes. So, you'd
have a C::A::Request, C::A::Response (which probably would be a
scalarref pointing to the text returned from the runmode that would a
blessing), and a few other items. Maybe, a C::A::RunModes,
C::A::Handler, etc.
Actually, now that I'm thinking in that direction, the easiest way to do
this would be to provide a C::A::Handler::Setup, C::A::Handler::Prerun,
etc. Those would take care of the tasks of:
1. Registering appropriately with the C::A class
2. Handling the singleton book-keeping (should this be necessary -
some handlers will probably be not instantiated, choosing to remain as
class methods)
3. Providing some useful methods/attributes
Taking a page again from MP, we could then specify a method name that
would be called in each object/classname. (You could register either an
actual object or the classname, depending on if you're instantiated or
not.)
Rob
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/cgiapp@xxxxxxxxxxxxxxxxx/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: cgiapp-unsubscribe@xxxxxxxxxxxxxxxxx
For additional commands, e-mail: cgiapp-help@xxxxxxxxxxxxxxxxx
|