On Thu, 2003-07-24 at 02:18, Eric Sammer wrote:
> where did you (Perrin) keep 
> objects like your database handle (assuming DBI, but please correct 
> otherwise) and any objects that could be reused (TT, XML parser objects, 
> et al)?

People seem to ask about this frequently, but I don't think we did
anything especially interesting there.  We just had a simple class full
of accessors for these resources that would call factory methods the
first time and then cache the result as appropriate.

For example, to get a DBI handle you would call something like this:

sub get_dbh {
    my $r = Apache->request();
    my $dbh = $r->pnotes('ESF_DBH');
    if (!$dbh) {
        $dbh = ESF::Service::DB->new();
        $r->pnotes('ESF_DBH', $dbh);
    }
    return $dbh;
}

This caches the database handle for the rest of the request (one
Apache::DBI ping per request should be enough).

For the Template Toolkit object we want to cache it for the life of the
process, so it would be something like this:

use vars qw($Cached_Template_Object);

sub get_template {
    if (!defined $Cached_Template_Object) {
        $Cached_Template_Object = Template->new();
    }
    return $Cached_Template_Object;
}

We also did things in there like setting the include path for the
current request, but you get the idea.  These are all class methods in
the ESF::Util class.

> I see a reference to a utility style class (ESR::Util, IIRC), but after 
> rereading a number of articles and design pattern books, I'm reluctant 
> to go with a "handle holder" object as I've done in the past.

Gang of Four got you spooked?  If you have something that works and
doesn't cause problems elsewhere in your code, don't fret about it.

> What I'd like is to have my model (as in MVC) objects reuse the 
> process or maybe even server shared objects without doing any of these:
> 
> 1. Using a singleton utility class
> 2. Needing to pass objects to model objects' new() in teh controllers
> 3. Instantiating the objects in the model classes themselves

All of those sound legit to me, as long as you don't duplicate code
between the objects.  I would choose #1, personally.

> I guess I could use a class to just act as a namespace to hold the 
> objects and create them at server startup time and use a module like 
> IPC::MM, File::Cache, or Cache::Mmap but that feels kludgy and offers no 
> encapsulation for the objects themselves.

No, you can't share things like this between processes.  Things with XS
code, open sockets, filehandles, etc. are not shareable.

I think the way we did it in the above code (don't fetch it until it's
asked for and then cache it as long as you safely can) is a good
approach, but you could refine it by having it set up some things in the
child init hook.

> Perrin - Have you ever considered revealing more about the Etoys project 
> or just the concepts as you applied them? It would be nice to peek at 
> some of the details. Or, is this an NDA situation or some such thing? 

Well, I don't have permission to go posting big chunks of code, but in
terms of the generally applicable ideas, I think the article covered
most of it.  The rest has to do with database work and patterns for
building model objects, and I hope to cover that in the article version
of the talk I gave about object-relational mapping tools at this year's
Perl Conference.

The biggest thing the article didn't cover is the ideas used by the guys
coding the more interactive parts of the application to express the
state machine implemented by each of their modules in a declarative data
structure.  This was largely invented by Adam Sussman, who is at
TicketMaster now.  It was similar to what you see in CGI::Application
and some of the other frameworks.

- Perrin

Reply via email to