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

I need some advice pertaining to automation of dynamic Web content. In the organization I work for, we are currently working on creating and maintaining a large number of (often very complex) CGI apps. As the number and complexity of these applications grow, and as the due-dates shorten, we're exploring options of doing things a better way.

Currently we use CGI.pm and DBI, along with some methods in a "home-made" package, to generate both the content and layout of our web applications. Over the past few days, I've been reading up extensively on Template Toolkit, HTML::Template, CGI::Application, FormBuilder, etc.

Currently, I feel that the Template Toolkit may be the best option for us in regards to splitting logic from layout. I especially like the way it allows you to easily build more complex templates from smaller componenent templates. However, I'm also becoming interested in using CGI::Application to power the logic end of application development.

The main question is: what are your thoughts on the ideal combination? I know CGI:Application was built with the use of HTML::Template in mind, not Template Toolkit. However, it seems that it's probably possible to use the Toolkit with it instead. Is this a bad idea? Would it make life more complex, or easier? The point here is to create complex apps as fast as possible, and to make them as extensible and reusable as possible at the same time.

Along the lines of layout and design, I also have this question: what about using CSS and templates together? Is it a good idea to use one or the other exclusively, or would it be beneficial to use stylesheets as an extra layer of design on top of the templates?

Basically, we need to be able to make an informed decision soon, and we're still not quite sure which way to go. Any thoughts and recommendations would be VERY much appreciated.

Thank you so much!

Replies are listed 'Best First'.
Re: CGI::Application, Templates, and CSS
by rob_au (Abbot) on Feb 01, 2002 at 03:18 UTC
    The framework offered by CGI::Application is very straight-forward and direct and from my experience, allows you to prototype applications very quickly.

    While its true that CGI::Application has been built with a bias towards usage of HTML::Template for templating, there is absolutely nothing to stop you from using the Template Toolkit.

    Indeed, you can implement the usage of Template Toolkit within CGI::Application via two means:

    • Build your own class on top of the CGI::Application base class, overwriting the load_tmpl method with your own template initiation module - This is a very easy thing to do given the design of CGI::Application as a base class. ALternatively, you could initiate the Template Toolkit object within your scope and simply ignore the load_tmpl method inherited from CGI::Application.
    • Subsequently, once the Template Toolkit object exists within the scope of your application, you can return the result of $template->process( $file, $params ) at the end of the application, much in the same way you would with the output method of HTML::Template.

    Additionally too, the integration of CSS with your templates should be encouraged as you then have the benefits of not only the separation of code and interface (CGI::Application and Template Toolkit), but also interface separation of content and context (HTML and CSS).

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Re: CGI::Application, Templates, and CSS
by dreadpiratepeter (Priest) on Feb 01, 2002 at 15:15 UTC
    Look at HTML::Mason before choosing a solutions. You might find it helpful. I have achieved staggering success using it for large scale, highly interactive web sites.
    It follows a component model, it allows filtering of pages, it can automate headers, footers, navbars, etc.
    It plays well with CSS. My sites are completely style-sheet driven. And since the pages are made of of simpler, generic components,; at the page level I almost never have to worry about styles (or headers, or menus, or event behavior).
    It plays well with mod_perl and Apache::Session, making maintaining state a breeze.
    It may not be the answer for you, but you should check it out before making a decision.
    You can see it at MasonHQ.

    -pete
    Entropy is not what is used to be.
Re: CGI::Application, Templates, and CSS
by theguvnor (Chaplain) on Feb 01, 2002 at 03:32 UTC
    I second rob_au's appraisal of CGI::Application - it is a marvelous framework for maintaining clean applications. And you definitely don't need to use HTML::Template - you are free to push your output through whatever templating system you want. Two thumbs up for CGI::Application.
      Thanks much to the both of you! I figured I was on the right track with CGI:Application and Template Toolkit, but I'm a fairly new at this--the confirmation is much appreciated! I love this place!
        Why don't you grab a user id and stay a while then? :^)
Re: CGI::Application, Templates, and CSS
by Ryszard (Priest) on Feb 01, 2002 at 13:08 UTC
    I love CGI::Application and HTML::Template. its seriously good stuff. In my experience its the bet way to build a scalable site.

    If you add in a mix of mod_perl and DBI, you can make your site do whatever it needs to.

    One thing i did notice when I started using CGI::Applicaiton was if you dont plan your application correctly, you can get bogged in lots of run modes, that reference each other. Quickly becomes spaghetti, and ma

      Hi, I discovered CGI::Application a couple of weeks ago, and was shocked at how well structured it made my applications. Unfortunatley as they've grown, i've encountered what you mention in your post, lots of runmodes, and most of them call each other as an easy way of handling error conditions.

      sub show_monkey { my $self = shift; my $db = $self->param('db'); my $q = $self->query(); my $monkey_id = $q->param('monkey_id'); my $ref = $db->select_monkey($monkey_id); unless ( defined($ref) ) { $self->param('error' , "Invalid Monkey ID: $monkey_id in show_monk +ey()"); return $self->show_all_monkies(); } my $tmpl = $self->load_tmpl('show_monkey.tmpl'); $tmpl->param( $ref ); return $tmpl->output(); }
      To try and simplify things, I moved all of my database calls into a seperate object that was initialised with my main CGI::Application and set as the db param. This simplified the main portion of my code, but there is still a great deal of runmodes all calling each other.

      Do you have any tips on how best to structure the runmodes? I seem to have a lot of add_blah1 , edit_blah1 , delete_blah1 runmodes, is there a better way to handle that?

      Also while i'm asking questions. I have a couple of CGI::Application objects now, one say Monkey::Gallery and another Monkey::News is there a tidy way to call one of the runmodes of Monkey::News (recent_news) for example that can be passed as a param into my main Monkey::Gallery page?

      Anyway, any advice anyone can give me would be greatly appreciated. I've been using perl for years now, but have only really started writing stuff on a scale to start worrying about how tidy and modular it is. (I'm reading Design Patterns so i'm on the ladder).
      Many Thanks,

      Steve

        I guess the best advice i can give you is, if you do it more than once, make a seperate subby (or method).

        For my web apps, i've extracted all my db calls into two subroutines, one for selecting and one for updating.

        Do a concept model of your apps, and put all the concepts you've found into discrete buckets.

        Do you have any tips on how best to structure the runmodes? I seem to have a lot of add_blah1 , edit_blah1 , delete_blah1 runmodes, is there a better way to handle that?

        If that there are several methods to a concept, perhaps you could create a 'super routine' that you pass flags to inorder to perform the varous functions.

        For example if you have 3 methods add, edit, delete, you could make a routine that you pass the flags to {method=>'add'} and your routine would get the approprate sql, do the varous functions et al.

        This thing is kind of contentious (and subjective) as it is combining several different methods in one function, which would normall be split into the 'high-cohesion, low coupling' style.

        If you build the underlying infrastructure (ie dbi calls, content aggregation et al), and parameterise is accordingly (ie build your routines in a very generic manner) you can build the business logic for the (add, update, delete) functions in one routine that would farm out the physical operations to you prebuilt infrastructure and return $output.

        As I mentioned your style to abstraction is subjective, and before putting fingers to keyboard I would suggest having a good long think about your logic, with a view to code reuse, even going so far as to sketch it out on paper.

        The approach i use is a three tier approach:
        1st tier: the application or user input level
        2nd tier: the signal box level. The input from the user is interpreted, and calls are made to the bottom layer.
        3rd tier: The layer that goes and actually *does* things. ie i'll make my dbi calls, do my content aggregation etc.

        I code in this manner, and it works for me.

        So in your example you could do something like:

        rm=mode1&method=add; rm=mode1&method=edit; rm=mode1&method=delete

        Of course everything has extremes, and if you have 20 methods for a concept, perhaps this is not the best method to persue.

        Update: I've just noticed youre not untainting your $q->param() variables before reassigning them. I dont know what the rest of your code looks like, so you may have done it elsewhere. If not, you must untaint all externally assigned variables before using them if you want to build a secure web applicaiton. This inclues both sides of your app, ie the user input end and the database/os end.