Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

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

by saberworks (Curate)
on Nov 02, 2004 at 00:20 UTC ( [id://404473]=note: print w/replies, xml ) Need Help??


in reply to Re^2: CGI::Application, inheritance trees, and 'the right way'
in thread CGI::Application, inheritance trees, and 'the right way'

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.

Replies are listed 'Best First'.
Re^4: CGI::Application, inheritance trees, and 'the right way'
by drewbie (Chaplain) on Nov 02, 2004 at 18:37 UTC
    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. :-)
Re^4: CGI::Application, inheritance trees, and 'the right way'
by geektron (Curate) on Nov 02, 2004 at 03:39 UTC
    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 ...

      Actually you can put them anywhere, but you're probably right they should be put at the top since they're included at compile-time anyway.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2024-04-19 22:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found