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