-- Mark Stosberg <[EMAIL PROTECTED]> wrote (on Saturday, 02 October 2004, 02:35 AM +0000): > On this list there was just a thread which brought to light how > people access databases through CGI::Application. There were three primary > groups of answers: > 1. Custom SQL called directly from the CGI::Application project. > 2. Using custom "Data Access Objects" to abstract the issue > 3. Using Class::DBI as a standard solution. > > I'd like to discuss this issue a little more broadly: What's an > effective way to to structure your application once you realize it makes > sense to move some logic into helper modules? Munging data as it comes > in and out of the database is probably the most common need for this. > > Here are some approaches I can think of: > > 1. A purely orthogonal module > > Here, the helper module has no dependency or relation to > CGI::Application. Most other modules you might employ from CPAN would > fall into this category. For example, using CGI::Simple, SQL::Abstract > or Data::Grouper. > > In many ways, this is the ideal setup, because the lack of > interdependence reduces the overall complexity of your application. > > Unfortunately, writing this of module for a custom solution can tedious > if there /are/ a lot of interdependencies you want to consider, such as > sharing configuration data, a database handle, session information or > CGI query parameters.
This is the way I write my applications. I came to this from a variety of directions: 1. MVC pattern -- to which I was introduced via CGI::App, suggests that the business logic code is orthagonal to the view code is orthagonal to the controller code. Now, the controller falls into a wierd area in that it needs to communicate between two orthagonal systems, but I find that that's actually fairly easily done. The way I write my systems, the controller simply worries about processing the input, using that (filtered) input to pass data to the model, process the response from the model (if necessary) and pass that data to the view. It's not completely orthagonal to the view, as the view may require certain input and forms of input -- which means if the view changes, the controller may need to change as well. It makes for some work at the beginning -- but in the end very much simplifies everything. I think of my model as an API -- it expects certain arguments, and gives back certain results. If I follow that strictly, then creating the model is fairly straightforward -- and using it from the controller is usually a matter of only a line or two of code. And if you do it right, your API can accept a DB handle as an argument to instantiation, and simply doesn't care about such things as session information or CGI query parameters -- they fall outside its scope. That's the domain of the controller. 2. The book, "The Pragmatic Programmer," introduced me to the concept of domain languages. If you haven't read the book, do; it has definitely changed some aspects of how I program. Among other things, it has several nice discussions about code reuse and orthagonality that I've found indispensable. I actually learned a lot about MVC from it, too. One thing I think about often is, 'what is the domain of this piece of code?' PP talks about domain languages as language sub/supersets specific to the task, or 'domain', but one other way of thinking about them is what task or tasks are specific to the domain at hand. So, if I'm working on the API and find myself worrying about validation of parameters, I stop; validation is the domain of the controller. If I find myself in the view (i.e., editing a template) and find myself worrying about what session variables might be set and how to get at them... I instead request them from the controller. Similarlly, if I'm working in my controller (a CGI::Application class), and want to pull something directly from the database... again, I stop, and I add a new method to my API for that action. 3. Code reuse, particularly in different ways. If I have a nice, clean API developed, I can use it in a variety of ways, not just from my web-based controller. For instance, if I've created an event calendar, and have an API that covers adding, updating, listing, retrieving, and searching events, I could create scripts/libraries that access that same API via a command line interface, email, a GUI, etc. If any of it were dependent on web-specific items -- a session, or a CGI parameter -- it wouldn't work. <snip> > 2. Re-process the CGI object everywhere. > > I was optimizing some code that used this construct a lot: > > my %FORM = $self->query->Vars; > > Instead of passing around the CGI query parameters I needed, I just > relied on having the query object handy, and re-created a convenient > hash of the query parameters. It turns out this is an expensive > operation in CGI.pm, and it was a primary source of slowness in my code. > > As one routine called another, each was re-processing the CGI params, > so that some lower level CGI.pm functions were being called thousands of > times for a single request. Oops! I've fallen down that trap as well. I now typically grab all the parameters I'll be processing and throw them into a param() -- that way I can utilize them from anywhere without making successive calls to the CGI.pm object. -- Matthew Weier O'Phinney [EMAIL PROTECTED] http://weierophinney.net/ --------------------------------------------------------------------- Web Archive: http://www.mail-archive.com/[EMAIL PROTECTED]/ http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2 To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
