<?xml version="1.0" encoding="windows-1252"?>
<node id="478922" title="The Power of Objects" created="2005-07-28 07:45:43" updated="2005-08-14 06:03:35">
<type id="120">
perlmeditation</type>
<author id="394960">
Mutant</author>
<data>
<field name="doctext">
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.
&lt;br&gt;&lt;br&gt;
&lt;readmore&gt;
&lt;b&gt;The Problem&lt;/b&gt;
&lt;br&gt;&lt;br&gt;
I've got a mod_perl application that uses [cpan://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 [cpan://Catalyst] now), and since it was a fairly simple app, I rolled my own.
&lt;br&gt;&lt;br&gt;
This just consisted of a Handler that created my own Request object, and passed this to every 'crontroller' function. It included an [cpan://Apache::Session] object, database connection, etc.
&lt;br&gt;&lt;br&gt;
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.
&lt;br&gt;&lt;br&gt;
I wrote some code to read the administrator flag from the DB, and store it in the session - nothing tricky there.
&lt;br&gt;&lt;br&gt;
&lt;b&gt;Wrapping HTML::Template&lt;/b&gt;
&lt;br&gt;&lt;br&gt;
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.
&lt;br&gt;&lt;br&gt;
Luckily, HTML::Template is OO, so all I needed to do was sub-class it. This was pretty straight forward:
&lt;code&gt;
package MyApp::HTML::Template;

use base qw(HTML::Template);

sub new {
    my $class  = shift;
    my %params = @_;

    return $class-&gt;SUPER::new(
        %params,
        die_on_bad_params =&gt; 0,
    );
}
&lt;/code&gt;

At the same time, I figured I'd default that pesky die_on_bad_params to off, since I hardly ever use it.
&lt;br&gt;&lt;br&gt;
Then all I had to do was change every call to HTML::Template-&gt;new() to MyApp::HTML::Template-&gt;new() - a simple find &amp; replace.
&lt;br&gt;&lt;br&gt;
&lt;b&gt;Passing the Flag&lt;/b&gt;
&lt;br&gt;&lt;br&gt;
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.
&lt;br&gt;&lt;br&gt;
&lt;code&gt;
sub param {
    my $self = shift;
    my %params = @_;

    $self-&gt;SUPER::param(%params);
}
&lt;/code&gt;
&lt;br&gt;
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.
&lt;br&gt;&lt;br&gt;
After a bit of thinking, I realised I just needed to make my Request class a singleton. This was as simple as inheriting from [cpan://Apache::Singleton] (this module was necessary rather than [cpan://Class::Singleton], so that the singleton is destroyed at the end of the mod_perl request).
&lt;br&gt;&lt;br&gt;
Then, from the param method, I can simply call &lt;code&gt;MyApp::Request-&gt;instance()&lt;/code&gt; and I'll have the request object with the flag I need, which can then be passed to param().
&lt;br&gt;&lt;br&gt;
&lt;b&gt;Conclusion&lt;/b&gt;
&lt;br&gt;&lt;br&gt;
&lt;/readmore&gt;
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.
&lt;br&gt;&lt;br&gt;
&lt;font size="1"&gt;&lt;b&gt;Update&lt;/b&gt;: Fixed a spelling error&lt;/font&gt;&lt;br&gt;
&lt;font size="1"&gt;&lt;b&gt;Update 2&lt;/b&gt;: Updated constructor, as per [node://jeffa]'s suggestion.&lt;/font&gt;&lt;br&gt;</field>
</data>
</node>
