Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
I've never been a huge advocate of OO; I use objects when it's convenient. However, the more code I write, the more I begin to realise that I should be using objects a lot more. A recent solution to a problem I had re-enforced this for me. Although this is probably pretty obvious to a lot of Monks, I thought I'd share my story with you, in case someone finds it useful.

The Problem

I've got a mod_perl application that uses HTML::Template throughout. At the time I wrote it, there wasn't any off-the-shelf framework that I really liked (I'd probably use Catalyst now), and since it was a fairly simple app, I rolled my own.

This just consisted of a Handler that created my own Request object, and passed this to every 'crontroller' function. It included an Apache::Session object, database connection, etc.

The problem was, I needed to add an item to the main menu (displayed on every page) for administrator users only. Previously, there hadn't even been an administrator user, but I did have a 'top.html' template, included by every other template with the menu.

I wrote some code to read the administrator flag from the DB, and store it in the session - nothing tricky there.

Wrapping HTML::Template

I didn't like the thought of passing an adminstrator flag every time I made a call to HTML::Template's param(), so I obviously needed to wrap it.

Luckily, HTML::Template is OO, so all I needed to do was sub-class it. This was pretty straight forward:
package MyApp::HTML::Template; use base qw(HTML::Template); sub new { my $class = shift; my %params = @_; return $class->SUPER::new( %params, die_on_bad_params => 0, ); }
At the same time, I figured I'd default that pesky die_on_bad_params to off, since I hardly ever use it.

Then all I had to do was change every call to HTML::Template->new() to MyApp::HTML::Template->new() - a simple find & replace.

Passing the Flag

Ok, so I had a wrapper for every call to HTML::Template, but now I needed the flag to be passed in to each template. Again, I didn't want to do this every time I called param(), so I obviously needed to override it.

sub param { my $self = shift; my %params = @_; $self->SUPER::param(%params); }

Great, but now I had a problem. The Request object wasn't accessable from my wrapper class - it's out of scope of course. And I didn't want to pass *that* in every time.

After a bit of thinking, I realised I just needed to make my Request class a singleton. This was as simple as inheriting from Apache::Singleton (this module was necessary rather than Class::Singleton, so that the singleton is destroyed at the end of the mod_perl request).

Then, from the param method, I can simply call MyApp::Request->instance() and I'll have the request object with the flag I need, which can then be passed to param().


I've often been suspicious of the 'use objects unless you have a really good reason not to' attitude, but as I learn more, I find that even if there doesn't seem to be a really good reason to use OO at the time you write something, when it comes to maintenance, OO can often make your life a lot easier.

Update: Fixed a spelling error
Update 2: Updated constructor, as per jeffa's suggestion.

In reply to The Power of Objects by Mutant

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others drinking their drinks and smoking their pipes about the Monastery: (5)
    As of 2018-03-21 05:35 GMT
    Find Nodes?
      Voting Booth?
      When I think of a mole I think of:

      Results (263 votes). Check out past polls.