in reply to (Ovid) Re: package identifiers and scope question
in thread package identifiers and scope question

Thanks, Ovid, the tutorial was very useful.

OK, so you can stop burning and I can gain some enlightenment:

I am writing a cgi to run a website using a mysql database. I have to pass various objects around (cgi query object, database handle, et.al.) and it is tiresome to have to explicitly pass these things through multiple functions. I have a main program, a "web pages module", and a "utilities module" to keep the code logically separated. It isn't a huge application and I'm the only one working on it (for myself, not for a company), so it seemed easiest to use a very few global variables. However, if you can suggest a better way, I'm all ears...er...eyes!

Thanks!
Apprentice
  • Comment on Re: (Ovid) Re: package identifiers and scope question

Replies are listed 'Best First'.
(Ovid) Re(3): package identifiers and scope question
by Ovid (Cardinal) on Sep 05, 2001 at 22:23 UTC

    apprentice, I understand your reasoning, but this is an excellenent example of why you don't want to use global variables. You may want to read about good programming practices and how you can get bit violating them.

    The larger an application grows, the more items tend to need access to global variables. While I realize that you don't want to pass around a bunch of different objects and variables, it's very, very easy to lose track of where you're instantiating them, changing them, etc. However, if code is written tightly enough, I find that there's less passing around of these objects than one would think. Usually, you're passing the data gotten from the objects than the objects themselves.

    What would be the best way for you to approach this would vary greatly upon your application needs. I don't know what you're use you're putting your CGI objects to, for example. Let's say, for example, that you're only using the CGI object for the CGI::param() method. You could package all of your objects into an "application" object and just pass that around instead of all of the objects and data. What follows is a much different solution from what others suggest and I'm not wild about it, but I though I would toss it out there in the spirit of TIMTOWTDI.

    package My::Application; use strict; use DBI; use CGI; sub new { my $class = shift; my $q = CGI->new; my %data = map { $_, [ $q->param($_) ] } $q->param; my $href = { _dbh = connect_routine(), _data = \%data }; bless $href, $class; } sub form_data { # remember that all data returned from this is tainted!!!! my ( $self, $item ) = @_; if ( ! exists $self->{ _data }{ $item } ) { return undef; } elsif ( wantarray ) { return @{ $self->{ _data }{ $item } }; } else { return $self->{ _data }{ $item }[0]; } } sub get_user_info { my ( $self, $id ) = @_; # Note the placeholder .. greater security my $sql = "SELECT first, last FROM users WHERE id = ?"; my $sth = $self->{ _dbh }->prepare( $sql ); my $rc = $sth->execute( $id ); . . . }

    I think you get the idea from the above (very untested) example. With that, you encapsulate all application specific objects and data into one object and just pass that around. The objection I have to my method is that now you're mixing cheese and Wednesday. Frankly, I don't like the idea of mixing form-handling code and database code in one object, but this is just a rough idea to show you how it's done. On the other hand, if you reframe it with the idea that you're gathering all application specific data retrieval into one module, then I think it's justifiable.

    use strict; use My::Application; my $app = My::Application->new; # it's transparent to the programmer, but this is getting # the data from the submitted form data my $user_id = $app->form_data( 'user_id' ); # again, we have application specific data, but from # the database instead of the user form my $user_details = $app->get_user_info( $user );

    Cheers,
    Ovid

    Vote for paco!

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Re: (Ovid) Re: package identifiers and scope question
by John M. Dlugosz (Monsignor) on Sep 05, 2001 at 21:47 UTC
    Objects. Think Objects.

    The stuff you're passing around won't be global, it will be the instance data.

    —John