http://www.perlmonks.org?node_id=411810


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

When I do this kind of thing, I put the logic in the handling runmode

I don't think this will work very well. Often, mainscreen() itself took input from some other form. Now I'll need to pile on yet more logic inside mainscreen() to know which runmode it's being called by.

I don't see a solution with C::A that doesn't involve pileing on a lot of additional logic. It seems very good for applications that have a simple, linear progression through the pages (start -> A -> B -> C -> finish). It breaks down fast for more complex structures.

"There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Replies are listed 'Best First'.
Re^4: Review: CGI::Prototype
by Joost (Canon) on Dec 02, 2004 at 15:57 UTC
    /I'm assuming mainscreen() is just a call to a template in my response here...

    Why would mainscreen() change its appearance a lot based on where it was called from? It shouldn't really care - it should show data and messages and that's it. Use a different template for different screens, and include the common parts.

      Why would mainscreen() change its appearance a lot based on where it was called from?

      It may or may not change it's appearance. It may very well change what it does underneath based on where it's called from.

      For instance, I often create a set of forms for a user to go through to enter data that eventually ends up in a database. I have a second set that allows them to edit that information later. Really, the second set is exactly the same as the first set, just with the existing data pre-filled into the same forms, and we write our SQL to do UPDATE instead of INSERT.

      Since they're really the same thing with minor differences, and taking to heart the idea that copy-and-paste is the lowest form of reuse, we'll want to code things so that the same runmodes and templates can be used again.

      Certainly, C::A can do this (I've coded it to do just this many times). But I think a different approach (specifically, using polymorphic objects) could be a lot cleaner.

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

        I'm not sure how much cleaner the code would end up if you used polymorphism. I'm probably sceptic because of some experiences using Java Struts, where we ended up with an enormous class hierarchy trying to get at least *some* code reuse in the different actions (in Struts an Action is an object roughly equivalent to a run_method run_mode in CGI::Application).

        It's been noticed before that inheritance is often not the best way to handle code reuse, but Java and Struts don't give you much choice (if you want a reasonably simple API). In any case, spreading your code out over many classes that are all somehow related, even disregarding code reuse issues, makes the code hard to understand and adapt IMHO.

        I can see some potential in using Class::Prototyped (and hence, CGI::Prototype) in that regard, but I would have to try it "in the wild" to see if it really holds up.

        Right now, I like the fact that you can just group a bunch of related runmodes into one CGI::Application subclass: it makes their relationship explicit and you can make a shared base class to for bigger applications if you need that.

        updated: fixed typo

Re^4: Depends...
by Purdy (Hermit) on Dec 02, 2004 at 16:09 UTC
    I don't think this will work very well. Often, mainscreen() itself took input from some other form. Now I'll need to pile on yet more logic inside mainscreen() to know which runmode it's being called by.

    Well, it depends on your mainscreen(). My mainscreen() is always the very first page, which by definition doesn't take any input.

    In my years of cgiapp development, I actually haven't needed it any other way. That's probably b/c I don't develop the more complex structures, but I've done countless e-commerce and complicated database applications in this "simple" manner.

    Now that I think about it, there are a few other options. Remember in each runmode you got access to the $self (cgiapp class), which you can call its get_current_runmode() to see what runmode it's being called by. You also have access to the CGI object within. You can also stuff/access something inside the cgiapp object with its own param() method. Lastly, you can also pass along arguments to the various runmodes.

    You have to put that logic somewhere... ;)

      You have to put that logic somewhere... ;)

      Yes, and where I don't want it is in an if statement. I'd rather put the logic as a simple method call via polymorphism.

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

        I'm not sure what to say here... probably nothing. ;) I cannot grasp what you're really talking about and my cynicism meter goes up when people start throwing out large CS words. What's wrong with an if statement?

        Can you elaborate more on what you're trying to do? It sounds like:

        A (mainscreen) -> B (some dynamic data) -> C (data entry) -> B|C

        That right? If so, what does B do differently when it doesn't come from A?