Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^3: Review: CGI::Prototype

by xdg (Monsignor)
on Dec 02, 2004 at 21:22 UTC ( [id://411954]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Review: CGI::Prototype
in thread Review: CGI::Prototype

The update here is interesting and may get at the difference of approach between the two modules. (Caveat -- while I know C::A, my exposure to C::P is limited to this thread so far and a quick POD skim, so I may have it wrong. Apologies to the authors if so.) Both modules are effectively just state machines. However, the state-less nature of web-browsing means that tracking state and state transition is a bit more difficult.

The C::A approach with runmodes takes the approach that the runmode specifies a target -- a desired state, or really, a desired action which is usually to reach a certain state. The application reads the desired action from a parameter and dispatches to a subroutine for that action. The subroutine checks the validity of the action given the input and presents a new state back to the user. (This may be done within the runmode subroutine or as a call to a "display_x" subroutine.) Templates really define a state and logic in the templates specialize the state for special cases (e.g. redisplay a form with errors in red). Plus, templates define the the valid state transitions (runmodes) that can be called from a given state.

The C::P approach instead uses the information submitted to the application to determine the state the user was just in rather than the target. (Because of the state-less web, it can't assume that the new request originated from the last state displayed.) The state corresponds to a class, which examines the input to determine an appropriate state transition (from among valid state transitions for that state) and then calls a subroutine in a new class (state) to display back to the user. Classes define how to enter a state -- by displaying a template -- and how to exit -- by executing a state transition for a given input.

Syntax and templating systems aside, this conceptual difference seems to me to be the crux of the issue and preference for use may depend on how a programmer likes to think about it. In C::A, one defines state transitions and uses those to determine a new state to display. In C::P, one defines states and how a user gets from that state to other valid states.

Polymorphism becomes important in C::P as a way of handling special cases (e.g. a form with errors) without repetitive coding, whereas with C::A, the special case coding would more likely happen procedurally in the templates.

Hope that helps some people. (Just writing it was helpful to me to bend my mind around how to conceptualize states and transitions for CGI in general.)

-xdg

Code posted by xdg on PerlMonks is public domain. It has no warranties, express or implied. Posted code may not have been tested. Use at your own risk.

Replies are listed 'Best First'.
•Re^4: Review: CGI::Prototype
by merlyn (Sage) on Dec 03, 2004 at 12:44 UTC
    I think that's an excellent summary of C::P, and my understanding of C::A as well.

    With C::P, you define a view and its associated controller. (I got this model from Smalltalk many decades ago.) The controller presents the view, which the user interacts with, which the controller then decides what to do next: activating another controller, or staying in the same view. Of course, controllers share a lot of code, and that's where the class hierarchy comes in. And we need a meta controller to handle the stateless nature of the web to select which controller is active, and a piece of meta information (the "state") to help with that.

    Thus, I believe (other than the commitment to Template Toolkit, which can be overridden with a single method override, and the inclusion of a CGI.pm object for field interpretation) that C::P is the most generic framework you can create. So, based on that most generic structure, I have one concrete derivative that deals with using a hidden field (C::P::Hidden), but I suspect there will be others.

    I also have a nice testing tool, which nobody has talked about, C::P::Mecha, which allows WWW::Mechanize to "run" the application, but in the same process without a webserver. This alone is worth the price of the download. {grin}

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Now C::P sounds like Spoon/Spiffy
Re^4: Review: CGI::Prototype
by fizbin (Chaplain) on Dec 29, 2004 at 18:57 UTC
    So let me see if I've got this. State machines basically follow this cycle, after an initial setup:
    1. Look at your state and look in a table for what to do.
    2. Do stuff, probably depending on input, and figure out what state to go to next.
    3. Transition to the next state
    Now both C::A and C::P maintain state information by telling the browser "when you submit this form back to the server, come back in as state X". This is pretty much driven by the way HTTP works (the other choice is to use session ID variables and database lookups, but that tends to lead to un-web-like applications), so it's not surprising that they look alike in that respect. The difference is where in the state machine cycle the browser comes in. C::A seems from your description to put the browser into the last step; its state machine loop would be:
    1. Look at your state and look in a table for what to do.
    2. Do stuff, probably depending on input, and figure out what state to go to next.
    3. Tell the browser to come back in as the next state.
    4. Wait for the browser
    Whereas C::P seems to be:
    1. Look at your state and look in a table for what to do.
    2. Do stuff, and tell the browser to come back in as the second half of this state.
    3. Wait for browser
    4. Do some more stuff, probably depending on input, and determine what the next state should be.
    5. Transition to the next state
    Now, from just this description I'd expect the two application frameworks to be equivalent in the sense that an application could be switched between them by renaming some states and shuffling a bit of logic. The discussion so far would suggest that there are stronger differences. I'm not sure from this description which approach makes it easier to develop and maintain applications. The C::P approach seems more in line with what I'd want to do in typical data-entry or shopping cart web applications, but I'm wary of dismissing the C::A approach just because it doesn't immediately align with my current thinking. Lots of very useful tools don't align with my first impression of the problem domain.
    -- @/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/; map{y/X_/\n /;print}map{pop@$_}@/for@/

      I don't think that's quite right. In both cases, the logic flow is

      1. Receive a request from the browser
      2. Decide what do do about it
      3. Tell the browser to enter a new state
      4. Wait for the next request from the browser

      The difference is in the nature of (1) and the details of (2). I prefer to think about it this way:

      • C::A wants to know where you want to go, and decides based on that and the data provided where you actually end up.
      • C::P wants to know where you were and decides based on the data provided where you actually go next.

      For me, apart from style preferences, C::P works well where the validity conditions for entering particular states frequently depend on the current state. C::A is useful where the validity conditions for entering a particular state depend solely on the data requirements of the target state.

      If a C::A app always required a parameter for "current state" along with the "run mode" and used that plus other submissions to determine the state entered, it would provide the same functionality as C::P. C::P just enforces that kind of thinking from the beginning.

      -xdg

      Code posted by xdg on PerlMonks is public domain. It has no warranties, express or implied. Posted code may not have been tested. Use at your own risk.

Re^4: Review: CGI::Prototype
by mfuller (Novice) on Dec 04, 2004 at 21:33 UTC

    >Polymorphism becomes important in C::P as a way of handling special cases (e.g. a form with errors) without repetitive coding. Whereas with C::A, the special case coding would more likely happen procedurally in the templates.

    In C::A, when I have common processing I place it in a .pl file and require it in the proper modules. If I were better at OO, I guess I could make it a class and reference it similarly to what you describe for C::P.

    Do you know, is there a significant performance hit for doing everything in a C::P object model compared to C::A's model which (at least the way I use it) is more procedural programming within a basic framework of objects? Would this be a consideration for higher volume sites?

    Mark

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://411954]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (2)
As of 2024-04-20 04:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found