Re: Application design patterns
Perrin Harkins wrote: 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. Sorry to be so cliche / predictable. ;) This is what I'm sure will wind up happening. I think what I'm looking for will require this kind of framework. This caches the database handle for the rest of the request (one Apache::DBI ping per request should be enough). Maybe a stupid question, but what would be the functional difference between dumping the object after each request like you say and using the same method as you describe for the TT object below? I ask because I'm currently treating both objects the same way in two or three of my larger applications. I would assume this is to catch premature database shutdown or network trouble between an app server and database (cluster) on a request by request basis? Is this a performance related choice or an Apache::DBI best practices thing? For the Template Toolkit object we want to cache it for the life of the process, so it would be something like this: Right. This is what I currently do. 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. Quite true. I think when starting any new large application, as I am now, I like to reevaluate my current design methods and look at anything I might have been able to do better and do it - a bad (or good) habit. He who feels he got it right in the past never looks for a better way to do it in the future and, thus, stunts all learning and growth... or some such idealistic babble. ;) That said, I think what I'm learning here is that the uncomfortability with this design method is more in my head than tangible. 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. Yea... that seems to be the ticket, so to speak. 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. And now that you mention it, it seems so obvious. $Deity only knows what I was thinking... 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. Is this past tense and if so, is the article up somewhere? Just curious... 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. Hm... that is interesting as well. I've been poking at the internals of a lot of the "frameworks" out there and there are some fantastic concepts (Chris Winters' OI comes to mind). Or, there is the distinct possibility that I'm overly obsessed with architecture; that shouldn't be dismissed either... ;) Thanks for all your input and the great article(s). -- Eric Sammer [EMAIL PROTECTED] http://www.ineoconcepts.com
Re: Application design patterns
Aaron Ross wrote: Hi Eric, class. 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 I'm not sure if this violates 3 (the models classes have to know what resources they need, so i am not sure what wouldn't), but could you use a singleton for the resource and a factory to access it? The model classes call a "static" factory method that handles the configuration, cache, etc... This is what I'm thinking I'll do. It seems to be the most "natural" in this case. I was reading this paper by Andy Wardly http://www.template-toolkit.org/tpc5/camelot/index.html which has a collection of resource classes that seem to act in a similar method at some level (providing a resource with a class that could be implemented as a singleton). This solves the problem of having configuration and resource allocation code in your model objects. It does mean that you have to write factory classes for your resources, but they ought to be quite simple. Writing factory methods compared to littering code with instantiation of objects all objects are going to need lends itself to an easy and obvious first choice. ...For me, at least. ;) I've done a fair amount of Objective-C (Mac OS X Cocoa and Openstep) and there's a number of classes that work in a similar fashion - simple, clean, and functional. The reason I like it is because I don't need to worry about passing stuff around - just get a static instance and go to town. (For those interested or in the know, I'm talking about NSNotificationCenter, NSFileManager, and other similar classes). Thanks for the input! -- Eric Sammer [EMAIL PROTECTED] http://www.ineoconcepts.com
Re: Application design patterns
Perrin Harkins wrote: There are tutorials on the Template Toolkit site, a recent perl.com article about TT and Class::DBI, and my article: http://perl.apache.org/docs/tutorials/apps/scale_etoys/etoys.html I read Perrin's case study awhile ago and it was excellent. Out of curiosity (and since most of my code written prior to reading said article looks identical in structure) 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)? 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. I use a configuration object that parses and holds all site config info (DBI dsn, user, pass, TT paths, etc.), when apache starts - a singleton style class. 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 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. I'm sure I'm either overcomplicating the situation to some great extentent or the utility class is the way to go (combined with some caching / shared mem module). Is there some obvious pattern I've missed or should I just KISS? 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? Either way, great article. Thanks in advance. -- Eric Sammer [EMAIL PROTECTED] http://www.ineoconcepts.com
Re: Apache::Cookie - weird values returned...
Rob Lambden wrote: I've had problems with scripts and mod_perl code before where I inadvertently create keys in a hash when I'm testing to see if they exist. I now always use something Like: i always use either defined or exists as appropriate to avoid these errors. i've gotten bitten in the bottom by the same things many times in the past... i learned my lesson. ;) > If the key did not exist previously it may be created by this process. The key can exist but hold an undefined value. again, in this case, the key is an Apache::Cookie object which couldn't accidentally be created as a "simple" type like a string key can. Is this an internal redirect, or a redirect sent from the browser ? the logout handler expires the cookie, sets the Location header, and returns REDIRECT. in other words, it's not internal nor a subrequest (unless a returned REDIRECT with a Location header is still considered a subrequest - that would be a surprise to me). If it's internal then the cookie will still exist unless you deleted the key yourself, and if you run the request As a sub-request it can pick up the submitted cookie again even if you have deleted the key on your parent request object. yea... unfortunately, that's not the case here... the browser regains control enough to handle the Set-Cookie (again, unless my perl/mod_perl/cgi books are all out of date)... ;) If it's coming back from the browser are you sure that the browser isn't sending you an empty Cookie? the cookie is a real cookie (in the headers) with the absence of the value. specifically, the return value of the Apache::Cookie->value() method. Maybe some users have broken browsers ? with the current state of things, i'm sure that's part of it. :) that said, there's always a limited set of options on that front. most of my (personal) testing is with mozilla on linux built from source (gentoo portage, actually) but similar behavior is seen on my mac os x boxes. You might also want to check hoe the cookie gets expired. What is the expiry date that is set on the Set-cookie: header that goes back to the client, and what is the date on that machine? the expire *i'm* specifying is just a relative '-1D' to cause the browser to drop it. if there's a better way, i'm certainly open to suggestions. Could you make do with per-session cookies (which have no expory date, but are only valid for the duration of that browser session) ? actually, all of these cookies are per-session which is why this isn't a "hey, the building is on fire!" sort of problem. the logout is one of those superfulous things that might be needed should the non-tech staff force us to add the dreaded "save my username/password" feature to the site. either way, i'd rather try and get the problem out of the way prior to such escalation. Although it's helpful to get to the bottom of any issue, you might be more at peace if you just checked to see if the value of the cookie was valid. yea... i suppose that's an option (and it *was* like that). i just get scared when something isn't working exactly as i understand it to be. it's that age old developer mantra of "unpredictable working code is worse than predictable broken code." After all, who's to say that the cookie they're sending you is actually the same as the one you sent them in the first place ;) damn browsers... damn cookies. i'm still waiting (and will be for a long time to come) for two things: working stateful web development and flying cars... something tells me the latter is a more attainable goal. ;) (Just for the record I don't actually use Apache::Cookie myself I look in and set the headers) i used to do that all the time too. i've always felt that abstraction prevents errors in the long run (or at least makes them easier to find). being wrong sucks. thanks for the response... i'll give some of these ideas a shot (again, where applicable). -- Eric Sammer [EMAIL PROTECTED] http://www.linuxstep.org
Apache::Cookie - weird values returned...
All: I've got a strange Apache::Cookie issue that seems to have recently snuck up on me, although I've seen similar behavior in the past. I have a PerlAccessHandler called GroupAccess that handles all access to a site**. If there's a user_id cookie, it pulls urls allowed to that user from a db, otherwise, an "anonymous" set of urls that are allowed - certainly not rocket science. The problem is that the logout handler (which expires the user_id cookie) kills the cookie and redirects to / ok, but when the GroupAccess handler checks if the cookie exists (during the / request), $cookies->{user_id}* is defined, but the value seems to be an empty string ala "". This really makes things difficult. What is weird is that the Apache::Cookie object DOES exist, it's just the value that's all wacked out or just plain missing. Could it be bug in Apache::Cookie that only shows up during internal redirects (and when I'm not looking)? This problem is incredibly difficult to reproduce as it only happens about 1 out of ever 30 - 40 times... That said, when it does happen, users complain and that's not cool at all. * $cookies is a hash ref with cookie names as keys and Apache::Cookie objects as values. ** The site in question: http://www.bluemonkeystuff.com Thanks in advance! -- Eric Sammer [EMAIL PROTECTED] http://www.linuxstep.org