Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Re: CGI::Application, inheritance trees, and 'the right way'

by saberworks (Curate)
on Nov 01, 2004 at 22:01 UTC ( [id://404434]=note: print w/replies, xml ) Need Help??


in reply to CGI::Application, inheritance trees, and 'the right way'

Since I work with a fairly large set of scripts, I actually use one "main" CGI::Application to control say the "task" run-mode, and then have multiple chilren CGI::Applications to control the "subtask" run modes. This way, common functionality resides together and the code is all in manageable chunks. The main script is in charge of deciding which CGI::Application module to run.
  • Comment on Re: CGI::Application, inheritance trees, and 'the right way'

Replies are listed 'Best First'.
Re^2: CGI::Application, inheritance trees, and 'the right way'
by Joost (Canon) on Nov 01, 2004 at 23:35 UTC
      I don't inherit because there isn't really a parent-child relationship between the different modules. I'll explain in detail what I'm doing in my current project. It's done this way not because I designed it this way from scratch, but because I'm refactoring existing functionality from a mess of spagetti-code and using CGI::Application modules to split it up into managable pieces seemed like a good way to go.

      Say I have 3 main pieces of code for a shopping cart - user management, product management, and order management. In this case, I'd have one CGI::Application module that works on the run mode "action" variable. So we'd have three run-modes: user, product, and order.

      My "Main" CGI::Application would be using the "action" variable to decide the run-mode. It's only choices would be user, product, and order. Depending on which of these it is, it would instantiate another CGI::Application module of that type. So if the main run-mode is "user," it would do something like:

      my $user_app = new UserApp(...);

      The nice thing is that since each run-mode in "Main" is related to a different thing (user, product, or order), I can use those run-modes to set up the environment for each of those sub-run-modes differently. For example, if I have a "user" class which is used to do database interaction with the users table, I can create a user object and pass it to the User CGI::Application module as a parameter. That user object won't be created for the other modes if they don't need it.

      I should probably post some code, I'll try to write it as I do it, but this is untested:

      use strict; use warnings; package MainApp; sub setup { my $self = shift; $self->tmpl_path('./templates/'); $self->mode_param('action'); $self->run_modes( product => 'product', order => 'order', user => 'user' ); } sub product { my $self = shift; use Product; use ProductApp; my $p = new Product(); # Say this is an object with methods to int +eract with the products database my $pa = new ProductApp( PARAMS => { p => $p } # more args... ); return $pa->run(); } sub order { # Similar to product() } sub user { # Similar to product() } package ProductApp; sub setup { my $self = shift; $self->tmpl_path('./templates/'); $self->mode_param('task'); $self->run_modes( add => 'add', edit => 'edit', delete => 'delete' ); } sub delete { my $self = shift; my $cgi = $self->query(); my $p = $self->param('p'); if($p->delete($cgi->param('product_id'))) { return "The product was deleted!"; } else { return "There was a huge error."; } } 1;
      The thing to notice is that the sub-modules work off a different run-mode name ("task" vs. "action"), so if I wanted to grab that delete method, I could go like this:

      http://some-url/?action=product&task=delete

      And of course to actually get it to delete something you'd have to pass a product ID:

      http://some-url/?action=product&task=delete&product_id=1234

      The reason I have different classes/objects to do database interaction is because we do a lot of reports and processing with command-line scripts in addition to our CGI::Application modules. If they're abstracted out like that, we can use those interfaces to do stuff from command line scripts as well without having to rewrite the same DB queries in multiple places.

      Anyway, I know this doesn't really address your question about inheritance, but I, like other people here, really don't like to use inheritance unless there is really a parent-child relationship. Generally, at least for me, there isn't such a relationshiop among various CGI::Application modules, as those don't contain much "real" logic - they are just interfaces to the real DB work that goes behind the scenes.
        Say I have 3 main pieces of code for a shopping cart - user management, product management, and order management. In this case, I'd have one CGI::Application module that works on the run mode "action" variable. So we'd have three run-modes: user, product, and order.

        My "Main" CGI::Application would be using the "action" variable to decide the run-mode. It's only choices would be user, product, and order. Depending on which of these it is, it would instantiate another CGI::Application module of that type. So if the main run-mode is "user," it would do something like:

        my $user_app = new UserApp(...);

        You might want to take a look at CGI::Application::Dispatch. It does the same sort of thing in that it uses the URL to figure out the application & runmode. So the url "/app/product/delete?product_id=1234" would map to the YourPrefix::Product CGI::Application class (the prefix is configurable) and set the runmode for said application to "delete". It seems like the same as idea as your code above, but with less code you have to write. :-)
        this is the direction i was thinking, because the inheritance probably isn't the best way to be doing this.

        i assume you posted some pseudo-code, but really, the  use statements should be closer to the head of the module ...

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2024-04-18 15:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found