Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Clarifications in subroutines, CGI.pm, HTML::Template and performance

by sara2005 (Scribe)
on Jun 18, 2006 at 02:31 UTC ( #556047=perlquestion: print w/replies, xml ) Need Help??

sara2005 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Experts,

First, sorry if I had asked too many questions but all seem related to me. I recently started with perl and was happily working with the CGI.pm module and some modules from CPAN to create my web app. When I had doubts, I started searching in the web and referred to CGI programming in Perl by Shishir & Scott, online docs, etc, but was not to able to answer some of the (basic!!) questions. Hence, I am here hoping to get some wisdom from the experts. Would appreciate your thoughts, comments on the following.

1) I am creating ~10 web-pages using CGI.pm. As I need common headers and footers for the page, I call a subroutine to do that, which is defined in a separate module (say, common_subs.pm). In the first few lines of each cgi script, I instruct to "use common_subs" and "use strict" but it looks like I have to create a new cgi object in the main program as well as the module (which has the common subs). Since I do that twice, would that have any impact on the performance? especially with medium duty scripts? (If I don't use "use strict",I just create a new CGI object in the main script and the code is working fine. anyway, I am going to use "use strict" in my code by default but would appreciate your reasoning)

Here is some portion of the code..

#! /path/to/perl -wT # THis is the login validation script # Import CGI module use strict; use CGI qw(:all delete_all escapeHTML); use common_subs; use "path/to/other/modules/"; # Create a new CGI object my $query = new CGI; # Create query objects to retrieve input my $username=$query->param('user'); my $passwd=$query->param('password'); my $next_page = "http://somepage.com"; my $loginOK = check_login($username,$passwd); print $query->header; print $query->start_html(-title=>'Validate Login',-bgcolor=>'white', - +style=>{src=>'/IMG_PATH/templatestyles.css'}); # This is the common header defined in common_subs and # I use that in all scripts &display_header("Check Login"); if ($loginOK == 1) { print $query->b("Login successful! Loading next page....\n"); print $query->start_form(-name=>'data',-action=>$next_page); print $query->end_form(); print $query->script("setTimeout(\"document.data.submit();\",5000);"); } else{ print $query->font({-color=>"red"},$query->p("Login Failed!!!") +, $query->br(), $query->p("Please go back to login screen and enter c +orrect userid and password!!!")); ... etc... ... } # This is the common footer defined in common_subs and # I use that in all scripts &display_footer; print $query->end_html();

and the common subroutine is defined as follows in common_subs.pm:-

use CGI qw/:standard :html3 :all/; use strict; sub check_login{ .... } sub display_header { my $disp_text=$_[0]; # Note that I have to create a new CGI object here in the sub my $query = new CGI; print $query->center; print $query->table( { -border=>0}, Tr([ td( {-align=>"center" },[ $query->img({-align=>"center", +-src=>"logo.gif ", -border=>0 }), $query->font({-size= +>'4'},$query->b( $disp_text)), ]), ]), ); } sub display_footer{ ... ... }

2) I have downloaded some modules from CPAN and installed them in a different path. I define it as "use /path/to/other/modules" at the top of each script and also set some standard environment variables. Can I define these in the common_subs.pm , which I call in all scripts? (the idea is to define common items in one file so that it would be easy for maintenance)

3) I read about the HTML::Template module after having started doing my scripts in CGI.pm. Is it fair to say that if I use HTML::Template, my scripts would be organized better than just using CGI.pm? Again, is there any impact on the performance in terms of using HTML::Template rather than CGI.pm alone?

4) I have a tendency to create separate cgi scripts for each task. i.e., I call separate scripts to check login, execute commands, read and display menus, etc.. etc.. Should I minimize the no of cgi programs (as I know that each invocation of cgi script has some overheads - I use Apache, no of max users at a given moment not to exceed 15) or it is ok to go ahead with my approach?

5) How easy (or difficult) it is to move to mod_perl or any other better technology? (there are some links I found in the search but they are fairly old !!!)

As always, I look for your valuable comments

Replies are listed 'Best First'.
Re: Clarifications in subroutines, CGI.pm, HTML::Template and performance
by Asim (Hermit) on Jun 18, 2006 at 09:54 UTC
    Is it fair to say that if I use HTML::Template, my scripts would be organized better than just using CGI.pm? Again, is there any impact on the performance in terms of using HTML::Template rather than CGI.pm alone?

    As a GENERAL rule, yes, your code is improved by taking "display-only" aspects out of the Perl code proper. Much like modules, it makes the code easier to follow and read, and thus debug. By keeping your HTML as mostly-pure HTML, it also makes it easier to debug and validate it, as well.

    In terms of speed, switching to HTML::Template will make a mark. There are ways around that; Template Toolkit (sort of HTML::Template's big brother) will compile it's templates for added speed, and I suspect H::T has similar capacity. And indeed, a quick search on Google shows HTML::Template::Compiled and HTML::Template::JIT. Another cheap/easy way to help with CGI apps (this one more memory than speed) is to, when you're running with templating full-time, use a smaller version of the CGI module, like CGI::Simple, which takes out the HTML-generating portions of the full-bore CGI, leaving the bits that are for parameter-processing and header-generating.

    I have a tendency to create separate cgi scripts for each task. i.e., I call separate scripts to check login, execute commands, read and display menus, etc.. etc.. Should I minimize the no of cgi programs

    Frankly, with CGI, I worry far more about readability and maintaining of code. You pay such a cost in basic CGI overhead that shaving time for your CGI code is almost not worth it in many cases; if you want to optimize, do it after you convert to a mod_perl or similar setup, if you need to. However, staying with CGI-based solutions, I'd recommend you look into CGI::Application, which is a nice module for running multiple CGI "scripts" under one umbrella. If you're willing to make a bigger leap; I think you'll find a web framework like Catalyst to be a powerful ally; it has authorization routines as an easy-to-use module, for example.

    How easy (or difficult) it is to move to mod_perl or any other better technology?

    The more you code in a nice, easy-to-debug style, the better off you are with mod_perl. You might want to start with Apache::PerlRun, using the CGI conversion guide on the mod_perl site to sort out how to make this happen. Some of this will depend on if you're using mod_perl version 1 or 2, of course.

    If mod_perl is not your speed, there are other solutions, such as FastCGI.

    I hope this helps.

    ----Asim, known to some as Woodrow.

Re: Clarifications in subroutines, CGI.pm, HTML::Template and performance
by lima1 (Curate) on Jun 18, 2006 at 10:39 UTC
    You should definitely take a look at CGI::Application. Just create a Module with C::A as base, add your custom code to that module and then use this new module (eg. CGI::MyStdApp) as base for your CGIs.

    You can even package your common CGI::MyStdApp with Module::Starter to get an easy to install code base, and more important, no duplicated (for every app) code base.

    This OO approach is not very fast in a classical CGI environment, but runs with nearly no modification in mod_perl. In mod_perl, you can cache HTML::Templates. The bottleneck is here often firefox, not the perl script ;)

Re: Clarifications in subroutines, CGI.pm, HTML::Template and performance
by kiat (Vicar) on Jun 18, 2006 at 04:39 UTC

    No expert here but...

    I would restrict "use CGI" to common_subs.pm and let it handle all CGI related stuff. In my main script, I wouldn't expect to call "use CGI" since everything that I need for CGI parsing should already have been done via common_subs.

    Without a templating system like HTML::Template, you would most likely be mixing program code with html. This can lead to ugly, bloated code and possibly maintenance problems, especially as your code grows. So it's better to make use of a templating engine such as HTML::Template to allow you to move the html out of your code. That way, the resultant code is leaner and so easier to read and maintain.

Re: Clarifications in subroutines, CGI.pm, HTML::Template and performance
by wfsp (Abbot) on Jun 18, 2006 at 08:48 UTC
    Have a look at tachyon's Simple Module Tutorial for info on modules.

    My take on this would be to put the CGI.pm query object in the 'common code' module too. That way you only have to 'use CGI;' once.

    One way:

    #!c:/Perl/bin/Perl.exe use strict; use warnings; use MyCommon qw($q check_login common_footer); my $log_in = check_login(); print $q->start_html(-title => 'log in'); print $q->p($log_in); common_footer(); print $q->end_html;
    MyCommon.pm would look like:

    package MyCommon; use strict; use Exporter; use CGI; our (@ISA, @EXPORT_OK, $q); @ISA = qw(Exporter); @EXPORT_OK = qw($q check_login common_footer); $q = CGI->new; sub check_login { return "login ok"; } sub common_footer { print $q->p('common footer'); } 1;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://556047]
Approved by friedo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2021-04-11 03:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?